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:13


이 예제도 5.3.3 에 있는 두번째 테스트 프로그램입니다.

처음에는 10개의 부호 없는 정수를 무작위로 생성하고 그 다음에는 -50부터 +49 범위에 있는 10개의 부호 있는 정수를 생성합니다.

어셈블리어 - 난수 생성하기

 



  TITLE Link Library Test #2 (TestLib2.asm)

; Testing the Irvine32 Library procedures.

INCLUDE Irvine32.inc

TAB = 9 ; 탭을 출력하기 위한 Tab의 ASCII 값

.code
main PROC
call Randomize ; 뒤에서 사용할 Random 함수를 위해 Seed 설정. ( 이 함수를 호출하지 않으면 같은 값이 계속 나옴)
call Rand1                 ; Rand1 프로시저 호출
call Rand2                 ; Rand2 프로시저 호출
exit                          ; 종료
main ENDP

Rand1 PROC                     ; Rand1 프로시저 정의
; Generate ten pseudo-random integers. 10개의 부호 없는 정수 생성
mov ecx, 10 ; loop 10 times // ecx에 10을 넣어서 10번 반복되게 한다.

L1:                                   ; L1 루프 시작 부분 
call Random32 ;  Random32 함수 호출  - 무작위 int 생성 리턴값은 eax로 들어갑니다.
call WriteDec ;  WriteDec - eax에 있는 값을 출력해줍니다.
mov al, TAB              ; al에 Tab의 ASCII 값을 넣어줍니다.
call WriteChar        ; Tab의 ASCII 값을 출력합니다.
loop L1                     ; L1의 끝 - ecx가 0 이 아니라면 L1 의 처음 부분으로 돌아갑니다.

call Crlf                    ; 개행 
ret                            ; 리턴
Rand1 ENDP

Rand2 PROC                      ; Rand2 프로시저 정의
; Generate ten pseudo-random integers between -50 and + 49 - -50 ~ +45 에 해당하는 부호 있는 정수 생성
mov ecx,10         ; ecx에 10을 넣어서 반복문이 반복될 횟수 설정

L1:                                ; L1 시작 부분
mov eax, 100 ; 0-99
call RandomRange ; 무작위 int 형 생성 - 범위 안에서
sub eax, 50 ; 0 - 99 사이에서 생성 된 값에 50을 빼줍니다 
call WriteInt ; 연산 된 값을 출력해줍니다.
mov al, TAB ; Tab의 ASCII 값을 al에 넣어줍니다.
call WriteChar ; Tab 출력
loop L1                      ; L1의 끝 - ecx가 0이 아니라면 L1의 처음 부분으로 돌아갑니다.

call Crlf                     ; 개행
ret                            ; 리턴
Rand2 ENDP
END main 

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


책에서 보다가 괜찮은 샘플소스가 있어서 첨부해봅니다.

전경색과 배경색을 바꾸고

배열을 16진수로 출력하고

부호 있는 정수에 대해 입력을 받아서

입력한 정수를 10진수, 16진수, 2진수로 출력하는 샘플 코드 입니다.




TITLE Library Test #1: Integer I/O (TestLib1.asm)

;Tests the Clrscr, Crlf, DumpMem, ReadInt,
;SetTextColor, WaitMsg, WriteBin, WriteHex,
; and WriteString procedures.

Include Irvine32.inc
.data
arrayD DWORD 1000h, 2000h, 3000h                ; DWORD 형 크기가 3인 배열 arrayD 생성
prompt1 BYTE "Enter a 32-bit signed integer:",0 ; 문자열 생성
dwordVal DWORD ?                                      ; DWORD 형 변수 dwordVal 생성

.code
main PROC
; Set text color to yellow text on blue background:
mov eax, yellow + (blue * 16)              ; 배경색을 blue로, 글씨색을 yellow로 설정하겠다는 것을 eax에 입력
call SetTextColor                               ; eax값을 인자로 가져가는 SetTextColor 함수 호출로 설정
call Clrscr ; 화면 초기화

; Display the array using DumpMem.
mov esi, OFFSET arrayD ; arrayD의 오프셋을 esi에 저장
mov ecx, LENGTHOF arrayD ; arrayD의 길이를 ecx에 저장
mov ebx, TYPE arrayD ; arrayD의 타입, 즉 DWORD를 ebx에 저장(4가 저장됩니다.)
call DumpMem ; memory 출력. 위에서 입력한 esi,ecx,ebx를 기준으로 출력합니다.
                                                                ; 함수들에 대해 자세한 내용은 따로 포스팅 하겠습니다. 
call Crlf ; 개행

; Ask the user to input a signed decimal integer.
mov edx, OFFSET prompt1                  ; "Enter a 32-bit signed integer: " 문자열의 오프셋을 edx에 저장
call WriteString                                   ; edx에 있는 문자열 출력 
call ReadInt ; integer 입력 받기
mov dwordVal, eax ; ReadInt는 eax로 받은 값이 리턴되기 때문에 받은 값을 dwordVal 변수에 저장

; Display the integer in decimal, hexadecimal, and binary.
call Crlf ; new line
call WriteInt ; 부호 있는 10진수로 출력
call Crlf
call WriteHex ; 부호 있는 16진수로 출력
call Crlf
call WriteBin ; 부호 있는 2진수로 출력
call Crlf
call WaitMsg ; "Press any key..." 문자열 출력 후 키 입력 대기

; Return console window to default colors.
mov eax, lightGray + (black * 16)         ; 작업이 끝났으면 실행창의 환경설정을 다시 돌려줍니다.
call SetTextColor                               ; 바로 위에서 적용한 검은색 바탕에 밝은 회색으로 설정
call Clrscr ; 화면 초기화
exit
main ENDP
END main

Posted by NullBr4in