Programming/Assembly2012. 1. 26. 18:58


"인텔 기반 컴퓨터를 위한 어셈블리 언어 5판" 은 어제부터 시작한 어셈블리 교재입니다.

공부하면서 풀은 연습문제입니다.


1번 - 텍스트 색상 그리기

TITLE 5.8.1 example

; 5.8.1
; 텍스트 색상 그리기

 
INCLUDE Irvine32.inc
.data
printMsg BYTE "Assembly language - NullBr4in - ajlab.tistory.com", 0

.code
main PROC
mov eax, yellow
call SetTextColor
mov edx, OFFSET printMsg
call WriteString
call Crlf

mov eax, green
call SetTextColor

call WriteString
call Crlf

mov eax, cyan
call SetTextColor

call WriteString
call Crlf

mov eax, lightRed
call SetTextColor

call WriteString
call Crlf

mov eax, lightgray
call SetTextColor

exit
main ENDP
END main



2번 - 피보나치 수의 파일
 
 

 
Posted by NullBr4in
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
Programming/Assembly2012. 1. 23. 14:02


"인텔 기반 컴퓨터를 위한 어셈블리 언어 5판" 은 어제부터 시작한 어셈블리 교재입니다.

공부하면서 풀은 연습문제입니다.

1~4는 별로 필요가 없어보여서... 5~8번 문제만 풀었습니다.


5번 - 직접 오프셋 주소 지정

TITLE 4.7.5 eaxmple

;4.7.5-1
;5.1 직접 오프셋 주소지정


INCLUDE Irvine32.inc
.data
Uarray WORD 1000h, 2000h, 3000h, 4000h
Sarray SWORD -1, -2, -3, -4

.code
main PROC
movzx eax, Uarray
movzx ebx, (Uarray+2)
movzx ecx, (Uarray+4)
movzx edx, (Uarray+6)
call DumpRegs
exit
main ENDP
END main
  

5번 - 직접 오프셋 주소 지정 - 2
TITLE 4.7.5 eaxmple

; 4.6.5-2
;5.2 직접 오프셋 주소지정

INCLUDE Irvine32.inc
.data
Uarray WORD 1000h, 2000h, 3000h, 4000h
Sarray SWORD -1, -2, -3, -4

.code
main PROC
movsx eax, Sarray
movsx ebx, (Sarray+2)
movsx ecx, (Sarray+4)
movsx edx, (Sarray+6)
call DumpRegs
exit
main ENDP
END main 
 
6번 - 피보나치 수
TITLE 4.7.6 eaxmple

; 4.6.6
; Fibonacci
; 피보나치 수 12항 까지

INCLUDE Irvine32.inc
.data
first BYTE 1
second BYTE 0
sum BYTE ?

.code
main PROC

movsx ebx, first
movsx edx, second
mov ecx, 12
L1:
mov eax, ebx
add eax, edx
call DumpRegs

mov bl, dl
mov dl, al

loop L1
exit
main ENDP
END main
  
7번 - 산술식
TITLE 4.7.7 eaxmple

; 4.6.7
; 산술식
; EAX = -val2 + 7 - val3 + val1

INCLUDE Irvine32.inc
.data
val1 SDWORD 8
val2 SDWORD -15
val3 SDWORD 20

.code
main PROC
mov eax, val2 ; EAX = FFFFFFF1h
neg eax ; EAX = Fh
add eax, 7 ; EAX = 16h

mov ebx, val3 ; EAX = 16h, EBX = 14h
neg ebx ; EAX = 16h, EBX = FFFFFFECh

add eax, ebx ; EAX = 2h

add eax, val1 ; EAX = Ah

call DumpRegs
exit
main ENDP
END main
 


8번 - 문자열의 역방향 복사
TITLE 4.7.8 eaxmple

; 4.6.8
; 8. 문자열의 역방향 복사



INCLUDE Irvine32.inc
.data
source BYTE "This is the source string", 0
target BYTE SIZEOF source DUP('#')
.code
main PROC
xor esi,esi ; esi 초기화
mov esi, OFFSET source ; source 주소를 esi에 넣는다.
add esi, SIZEOF source ; esi가 source의 오프셋에 source 길이를 더한다.
dec esi ; 그럼 1 byte가 넘어가게 되는데 이걸 다시 빼준다.
xor edi, edi ; edi 초기화
mov edi, OFFSET target ; target 주소를 edi에 넣는다.
mov ecx, LENGTHOF source ; ecx(loop count)에 source의 길이를 넣는다.

L1: ; loop L1
mov al, [esi] ; [esi], 즉 source 주소지에 있는 값을 al 로 복사한다.
mov [edi], al ; al, 의 값을 [edi], target 주소이제 복사한다.
inc edi ; edi 주소를 1 증가시킨다.
dec esi ; esi 주소를 1 감소시킨다.
loop L1 ; L1 으로 돌아가라
mov esi, OFFSET target ; target 주소를 esi에 넣어라
mov ebx, 1 ; ebx에 1을 넣어라. DumpMem 에서 사용할 값 - byte format
mov ecx, SIZEOF target ; target의 크기(SIZE * LENGTH)를 ecx 에 넣어라.
call DumpMem ; DumpMem 호출.

exit
main ENDP
END main
 







이 중에서 8번은 약간 헤깔립니다..
뭔가 비효율적으로 코딩한거 같은데...
흠...........
 
Posted by NullBr4in