Programming/Assembly2012. 1. 26. 18:03


어셈블리어 명령어 정리는 시간 날때마다 한번씩 내용을 추가하겠습니다 ( 2012-01-26 )


 어셈블리어 명령어에 대해 정리할때 아래와와 같은 표기법을 이용해서 정리하겠습니다. 
 
  [그림 1] 인텔 IA-32 메뉴얼에서 채택한 피연산자에 대한 간단한 표기법



 MOV 
 - MOV 명령어는 소스 피연산자로부터 목적지 피연산자로 데이터를 복사한다.
 - MOV 복사하고자 하는 목적지, 복사할 대상이 있는 곳
 - MOV destination, source
 - MOV 명령어는 dest = source 와 같다 

 - MOV 명령어의 규칙
  + 두 피연사자는 같은 크기이어야 한다.
  + 두 피연산자는 모두 메모리 피연산자일 수는 없다.
  + CS, EIP, IP는 목적지 피연산자일 수 없다.
  + 즉시값은 세그먼트 레지스터로 이동될 수 없다.
 
 - 세그먼트 레지스터를 제외한 일반적으로 사용하는 MOV의 형태들이다.
  + MOV reg, reg
  + MOV mem, reg
  + MOV reg, mem
  + MOV mem, imm
  + MOV reg, imm

 - MOV 명령어를 사용할 때 한 메모리에서 다른 메모리 위치로 이동시키는데 사용하지 못한다.
   그러므로 다음의 방법을 사용한다.
  + var1, var2 는 WORD 형태를 가지고 있습니다.
    mov ax, var1
    mov var2, ax

 
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. 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
Programming/Assembly2012. 1. 23. 01:58


리버싱을 공부하면서 계속 어셈블리어에 대한 기초가 약하다고 느꼈었는데 

이번에는 시간 내서 기초를 잡고 가기로 마음 먹었습니다.

먼저 설치 전에 Irvine library 를 설치해주세요

이건 첨부파일에 첨부해놨습니다.



같이 첨부된 AsmHighlighter1_5.vsix 파일은 Visual Studio 에서 asm 코딩 할 때 보기 좋게 색을 넣어줍니다.



Visual Studio 2010 에 MASM 설정하는 것으로 시작해 보겠습니다. 
 



1. 먼저 첨부 파일을 받아서 압축을 풀어줍니다. 저는 C:\Irvine 폴더에 압축을 풀었습니다.


2. Visual Studio 2010 을 키신후, File -> New -> Project 를 하여 새로운 Project 를 추가합니다.


3. 'Win32 Console Application" 을 선택해주시고 이름은 아무거나 넣어주시고 OK를 눌러주세요. 저는 "asmtest"라고 넣었습니다.


4. 처음에 뜨는 창에서 "Next"를 눌러줍니다.


5. "Empty project" 에 체크하여 빈 프로젝트를 생성합니다.


6. 프로젝트가 생성되었으면, 생성 된 프로젝트에서 마우스 오른쪽 버튼을 누르시고 "Build Customizations"를 선택해 줍니다.


7. 그림에서 보이는 부분처럼 masm 에 체크를 해줍니다.


8. 이제 소스 파일을 생성해봅시다. Source File 폴더에서 마우스 우측 버튼 누른 다음 Add->New Items 를 선택해줍니다.


9. 위와 같은 창이 뜨는데, 여기서 "Utility" 에 있는 "Text File"을 선택해주고 이름을 넣습니다. 여기서 주의할 점은 확장명은 ".asm"


10. 소스 추가가 끝나셨으면 다시 프로젝트를 누르시고 우측 버튼을 눌러서 "Properties"를 눌러줍니다.


11. "Configuration Properties"->"Linker"->"General" 순서대로 들어가시면 "Additional Library Directories"가 있습니다.
     여기에 아까 설치한 Irvine library의 경로를 넣어주시면 됩니다.


12. "Configuration Properties" -> "Linker" -> "Input" 으로 들어가신다음에 "Additional Dependencies" 에 
     "irvine32.lib" 를 맨 앞에 추가해주세요. 추가하시고 뒤에 ' ; ' <- 을 꼭 넣어주셔야 합니다.


13. " Configuration Properties" -> "Microsoft Macro Assembler" -> "General" 에 들어가보시면 "Include Paths"라고 있습니다.
     여기에도 Irvine library의 설치 경로를 넣어주시면 됩니다.


14. 드디어 설정이 끝났습니다! 책에 있는 예제를 넣고 컴파일 해봅니다.


15. 정상적으로 작동되는 것을 확인합니다!! 

수고하셨습니다! 
Posted by NullBr4in