'어셈블리어'에 해당되는 글 1건
시스템 프로그래밍 레폿 발표 자료 :: 2006/10/07 17:55
※ 이 글은 학교 발표용 자료입니다. 그냥 설명하기 쉽게 글로 적어 놓은 겁니다. ^ㅁ^

일단 저희 조는 조장인 02학번 저 이정빈과 함께 04학번 문은미, 05학번 이가영, 김혜선, 마영주로 이루어져있습니다.
그럼 문제 설명에 앞서,
저희조에서 이 문제를 같이 공부했을 때 저희야 10분이 걸리든 1시간이 걸리든 5시간이 걸리든 발표전까지 이해하기만 하면 되지만, 이 발표자리에서는 제한된 시간안에 여러분들 모두에게 이해하기 쉽게 설명하기 위해서는 조금 다른 방법으로 이 문제에 접근할 필요가 있을 것 같습니다.
우선 1번 문제의 간단한 흐름과 1번문제의 비효율성에 따른 문제점들을 파악함으로써 저희 조가 발표할 2번 문제의 목적에 조금 더 쉽게 접근 할 수 있도록 하겠습니다.(1번 문제에 오류가 있다거나 잘못된 점이 있다는 뜻이 아닙니다.)
방금 전 1조에서도 들으셨겠지만, 다시 한번 간단하게 1번문제의 흐름을 정리해보겠습니다.
② R2 = R2의 값 + 49
③ R2의 값을 952번지로 저장
④ 956번지의 값을 R2로 로드
⑤ R2 = R2의 값 + 49
⑥ R2의 값을 956번지로 저장
⑦ 960번지의 값을 R2로 로드
⑧ R2 = R2의 값 + 49
⑨ R2의 값을 960번지로 저장
...
... 988번지까지 반복...
이런 3번의 작업들을 10번 똑같이 반복하게 됩니다. 결과적으로 Data1부터 10까지의 값에 49를 더한 결과를 갖게 되는 것입니다.
여기서 우리는 똑같은 작업과 달라지는 작업들 속에서 일정한 규칙을 발견할 수 있습니다.
우선 똑같은 작업으로는 ②,⑤,⑧ 번이 있고, 나머지 작업도 보면 색칠해진 부분에서 알 수 있듯이,
①, ③번의 번지수가 같고, 나머지도 똑같은 패턴입니다.
여기서 우리가 중복되는 부분을 최소화하기 위해 다음과 같이 생각할 수 있을 것입니다.
② R2 = R2의 값 + 49
③ R2의 값을 952 + R4 번지로 저장
④ R4 += 4
⑤ ①~③번 반복
이렇게 프로그램을 구성하면 코딩양이나 프로그램의 크기를 상당수 줄일 수 있습니다.
여기서 반복하기 위해 R3 변수를 10에서 시작해 1까지 반복하면 총 10번을 반복하는 효과를 볼 수 있습니다.
이를 쉽게 C문법 형식으로 소개하면 다음과 같습니다.(실제 메모리상에 저장되는 번지수나 크기는 고려하지 않기로 합니다.)
int R1=48, R2, R3, R4=0;
for(R3 = 10 ; R3 > 0 ; R3--) {
R2 = (952 + R4)번지의 값;
R2 = R2의 값 + 49;
(952 + R4)번지 = R2;
R4 = R4값 + 4;
}
위의 소스를 이해했다면 이제 실제 어셈블리어로 구현된 프로그램을 이해하는 것은 어렵지 않습니다.
상대번지 기준으로 차례차례 명령어를 설명하겠습니다.
1. 0번지의 명렁어는 4번레지스터의 내용을 지우는 명령어입니다. 4번 레지스터의 내용을 지우는 이유는 혹시 이 프로그램을 사용하기 전에 다른 프로그램이 4번 레지스터를 사용해 계산을 했을 수도 있고, 그 계산 결과가 아직 4번 레지스터에 남아있을 수 있기 때문에 다음에 사용할 명령어에 잘못된 값이 들어가는 걸 막기 위한 장치라고 할 수 있습니다.
2. 2번지의 명령어를 설명하기에 앞서 다른 명령어는 모두 4바이트를 차지하는 반면 0번지의 명령어 SR은 그 형태가 RR형식이므로 교재 33페이지와 같이 2바이트를 차지하기 때문에 다음 명령어의 위치는 2번지가 되는 것입니다.
2번지의 명렁어는 R2 레지스터에 Data1의 값을 로드시키는 과정입니다. 우리가 앞서 R4 레지스터를 비웠기 때문에 쉽게 생각해서 R4에는 0이 들었다고 생각하면 되고, 앞의 가정을 통해서 R1 레지스터에는 48이 들어있습니다.
그래서 Data1의 절대주소에 접근하기 위해서 904 + 0 + 48 = 952 라는 과정을 통하게 되는 것입니다.
3. 6번지의 명령어는 R2 레지스터에 로드한 사용자 데이터에 49를 더하는 과정입니다. 이 49란 값이 들어있는 절대주소 900 + 0 + 48 = 948 이라는 과정으로 값을 가져와 더하게 됩니다. 더한 값은 다시 R2 에 저장됩니다.
4. 10번지 명령은 더한 값을 다시 원래 처음 데이터를 가져왔던 장소에 다시 저장하는 명령어입니다. 잘 보시면 2번지에서 로드해왔던 주소와 같음을 알 수 있습니다. 결과적으로 레지스터에서 49를 더해서 다시 그 자리에 갖다 놓았다고 볼 수 있습니다.
5. 14번지 명령은 위에서 설명했듯 R4 레지스터에 4란 값을 더해줌을 의미합니다. 4란 값이 들어있는 절대주소는 896 + 0 + 48 = 944을 통해 가져올 수 있습니다. 이렇게 되면 다시 2번지의 명령이 반복되었을 시 4란 값이 더해지기 때문에 Data2에 접근 할 수 있게 되는 것입니다. 두번째 반복에서 2번지의 명령은 Data2에 접근하기 위한 절대주소의 계산은 904 + 4 + 48 = 956 이 되겠죠. 여기서 4란 값이 더해진 R4의 값입니다.
6. 18번지 명령은 R3 레지스터에 처음에 10이란 값을 로드 시킵니다. 이제 절대 주소에 어떻게 접근해서 10을 가져오는지는 설명하지 않겠습니다.
7. 22번지 명령은 R3 레지스터의 값에 1을 빼는 명령어입니다. 역시 뺀값은 R3에 다시 저장됩니다.
8. 26번지 명령은 R3에 저장된 값을 다시 처음 10의 자리에 대신 저장합니다. 1을 뺏으니 9가 저장되겠네요.
9. 30번지 명령은 위의 값이 양수이면, 2 + 0 + 48 번지로 분기하라는 명령어입니다. 앞의 2는 지정자로써 '양수이면' 이라는 뜻을 나타내고, 콤마 뒤의 값은 절대번지를 계산해서 그쪽으로 분기하라는 뜻입니다.
10. 다시 절대번지 50으로 이동하게 됩니다. 이 과정을 통해서 R4는 4가 늘어났고 10번반복을 위한 인덱스는 9로 줄어들었습니다. 이 과정을 앞으로 10번은 계속 반복하게 됩니다.
프로그램을 쭉 보시면 아시겠지만 우리가 직접 메모리에 접근해서 메모리상에서 더하거나 빼기 연산을 수행 할 수 없습니다. 항상 연산은 레지스터에서 이루어 짐을 알 수 있습니다. 49를 더한다거나 4를 더한다거나 1을 뺀다거나.. 잘 살펴보면 모든 연산은 레지스터에서 이루어지고 다시 그 계산된 값을 메모리는 저장만 하게 됩니다.
좋게 말하자면 역할 분담이 잘 되어있다고 볼 수 있고, 나쁘게 말하자면 멍청한건죠. 우리야 그냥 눈으로보고 49를 더해서 그 번지수에 값을 바꿔버리면 되니까요.
만약 다른 프로그램이 R4 레지스터의 내용을 바꿀 수 있다는 생각을 못했다는 것과 그렇게 쓸바엔 왜 처음부터 R4의 내용을 지우는 명령어를 집어넣었느냐의 문제입니다. 마땅히 R4의 내용도 메모리에 보관하였다가 다시 불러와서 값을 수정할 필요가 있습니다. 그것은 18번지 명령어를 보면 알 수 있습니다. 이미 R3의 레지스터에는 이전에 연산해서 1이 빼진 값이 들어있는 상태입니다. 그리고 이 값을 다시 메모리에 저장하는데 R4는 신경을 전혀 쓰지 않았다는 점에서 이 프로그램의 안전성이 의심되는 부분이라고 할 수 있습니다.

이 프로그램은 표에서 보시다시피 명령어로 34 바이트, 자료로 56바이트를 사용함으로써 총 크기가 90바이트만을 사용하여 처음 프로그램의 164바이트의 크기보다 훨씬 작은 프로그램이 되었습니다.
두번째 프로그램 역시 첫번째와 같은 원리이나 BCT란 명령어를 사용함으로써 R3 레지스터에서 1을 빼고 메모리에 저장하는 과정을 줄임으로써 프로그램의 크기를 약간 더 줄이게 되었습니다.
24번지만 간단히 설명하자면, R3 레지스터의 값에 10을 뺀 뒤 양수이면 절대주소 6 + 0 + 48 = 54로 분기하라는 명령어입니다.
별것도 아닌 프로그램을 대단한 것처럼 설명했네요. 참고 들어주셔서 감사드리며 이것으로 2조 발표를 마치도록 하겟습니다.



