Programming/Assembly2012. 1. 23. 17:11


5.4.2 장에서 스택을 이용한 문자열을 역순으로 배치하는 예제 입니다.

고급언어를 만지다가 저급언어를 만지게 되니  저급언어가 방법도 여러가지에 효율적이라고 생각되네요.



 TITLE Reversing a String (RevStr.asm)

INCLUDE Irvine32.inc
.data
aName BYTE "Abraham Lincoln", 0 ;  역순으로 배치할 문자열을 선언합니다
nameSize = ($ - aName) - 1 ; aName에 대해 문자열의 길이를 구하는 부분인데, 여기서 $ 는 
                                                                ; 현재 명령어의 위치 주소 입니다. 현재 주소에서 aName의 주소를
                                                                ; 빼게 되면 문자열의 길이만 남게 되는데, 여기서 널문자를 제외하기 위해 - 1 을
                                                                ; 해줍니다. 

.code
main PROC

; 스택으로 문자를 push 하는 부분 
mov ecx, nameSize                            ; 반복문에서 사용할 count 레지스터인 ecx에 문자열의 길이를 넣어줍니다.
mov esi, 0                                          ; esi에는 0으로 초기화 시켜줍니다. esi는 간접 피연산자를 이용한 간접 주소 지정
                                                                ; 을 통해 문자열을 하나하나 가리키게 됩니다. 

L1:                                                            ; L1 루프의 시작
movzx eax, aName[esi]                     ; aName+esi 위치의 문자열을 eax로 이동시켜줍니다. aName+0, aName+1 이런식
push eax                                           ; eax를 스택에 추가하고 - L,i,n,c,o,l,n,,, 이런식으로 스택에 쌓이게 됩니다.
inc esi                                               ; esi를 1증가시킵니다 - 다음 반복에서 다음 문자를 가리키기 위함입니다.
loop L1                                              ; L1의 처음부분으로 가서 반복합니다.

; 아래는 스택에서 문자를 pop 하는 부분.

mov ecx, nameSize                             ; 반복이 끝나면 0이 된 ecx에 다시 문자열의 길이를 넣어줍니다.
mov esi, 0                                           ; esi 또한 0으로 초기화 합니다

L2:
        pop eax                                              ; pop을 하여 스택의 맨 나중에 들어간 'n'을 꺼내옵니다.
mov aName[esi], al                            ; 꺼내온 값을 [aName+esi] 에 넣습니다.
inc esi                                               ; esi를 1 증가시킵니다.
loop L2                                              ; 루프의 처음으로 돌아갑니다

; 역 배치가 끝나고 출력 하는 부분.

mov edx, OFFSET aName                     ; aName의 offset을 edx에 저장합니다.                  
call WriteString                                      ; WriteString 함수는 edx에 저장된 주소의 위치에 있는 문자열을 출력합니다.
call Crlf                                               ; 개행
exit                                                    ; 종료
main ENDP
END main


Posted by NullBr4in
Programming/Assembly2012. 1. 23. 16:30


약 170억번 반복되는 반복문을 통하여 컴퓨터 성능을 시험해보는 예제 입니다.

반복문 시작 전 후로 현재 시간을 구하여 빼는 원리입니다.



TITLE Link Library Test #3 (TestLib3.asm)

; Calculate the elapsed time of executing a nested loop

INCLUDE Irvine32.inc

OUTER_LOOP_COUNT = 3 ; adjust for processor speed
.data
startTime DWORD ?
msg1 BYTE "Please wait...", 0dh, 0ah, 0 ; 0dh,0ah 는 개행문자입니다.
msg2 BYTE "Elapsed milliseconds: ",0
.code
main PROC
mov edx, OFFSET msg1 ; "Please wait..."이라는 문자열을 edx 에 넣습니다.
call WriteString ; 문자열 출력 - edx에 있는 주소의 문자열을 출력합니다.
; Save the starting time.
call GetMSeconds ; GetMSeconds - 자정 이후를 msec 단위로 계산하여 eax로 리턴
mov StartTime, eax ; eax 에 리턴된 값을 StartTime에 넣는다.
mov ecx, OUTER_LOOP_COUNT ; ecx - loop를 반복할 횟수를 넣어줌.

; Perform a busy loop.
L1:
call innerLoop ; innerLoop PROC 을 세번 호출한다.
loop L1

; Display the elapsed time.
call GetMSeconds ; 위의 루프가 끝나면 다시 한번 현재 시간을 구합니다
sub eax, startTIme ; 현재 시간에서 루프 시작하기 전 시간을 빼줍니다
mov edx, OFFSET msg2 ; "Elapsed milliseconds: "의 오프셋을 edx에 저장
call WriteString ; edx에 저장된 문자열 출력
call WriteDec ; eax에 있는 루프 도는데 걸린 시간 값을 출력
call Crlf ; 개행문자
exit ; main PROC 종료
main ENDP

innerLoop PROC ; innerLoop Proc 정의
push ecx ; 이전 루프에서 ecx가 사용되고 이번에도 사용되므로 스택에 저장함
mov ecx, 0FFFFFFFFh ; 반복 횟수를 FFFFFFFFh 로 지정
L1: ; L1 루프
mov eax, eax ; eax를 eax로 이동시키는 아무 의미 없는 코드 삽입
loop L1 ; L1 처음으로 . 
pop ecx ; 루프가 끝나면 이전 ecx를 스택에서 꺼내서 복원시킵니다
ret ; innerLoop Proc 을 리턴합니다.
innerLoop ENDP

END main

Posted by NullBr4in