• No results found

MASM muckmock pdf

N/A
N/A
Protected

Academic year: 2020

Share "MASM muckmock pdf"

Copied!
56
0
0

Loading.... (view fulltext now)

Full text

(1)

기술문서 ‘09. 07. 15. 작성

작성자 : 한국항공대학교 IDT 배건규

(2)

어셈블리

의 기초

1.

(MASM)

...3

데이터 전송 주소지정 연산

2.

,

...7

프로시저

3.

...13

조건부 처리

4.

...19

정수연산

5.

...28

고급프로시저

6.

...30

문자열과 배열

7.

...33

어셈블리를 이용한 블록 격파 게임 만들기

8.

...42

참고문헌

(3)

어셈블리 언어

의 기초

1.

(MASM)

어셈블리 언어의 기본적인 구성요소 1-1.

산술 연산 우선순위(Precedence) - 수식이 두 개 이상의 연산자를 포함시 연산의 순서 의미 ○

데이터 표현 ○

정수 상수 ⋅

[{+|-}] digits[radix]

h → hexadecimal(0A3h, 1Ah) b → binary(11010011b) q/o → Octal(42q, 42o)

실수 상수 ⋅

[sign]integer.[integer][exponent] -44.2E+05

문자 상수 ⋅

진 아스키 코드로 변환해서 사용 'A' or "d" → 2

문자열 상수 ⋅

"This isn't a test"

예약어(Reserved word) ○

인텔 프로세서에 의해 실행되는 명령어 니모닉(MOV, ADD, etc) ⋅

수식에 사용되는 연산자들 ⋅

같이 변수나 피연산자의 크기나 사용처를 알려주는 속성들 BYTE or WORD

에게 어떻게 프로그램을 어셈블해야 하는지를 알려주는 디렉티브 MASM

식별자(Identifier) ○

프로그래머가 선택한 이름 ⋅

사이의 문자가 가능 1~247

은 소문자 대문자를 구별하지 않는다

MASM , .

첫 번째 문자는 하나의 문자(A..Z, a..z)이거나 (_), @, $이어야 한다. ⋅

예약어를 사용해서는 안 된다. ⋅

연산자 이름 우선순위

( ) 괄호 1

+, - 단항 플러스 마이너스, 2

*, / 곱셈 나눗셈, 3

MOD 나눔자 3

(4)

디렉티브(directive) ○

프로그램의 소스 코드를 어셈블할 때 어셈블러가 인식하고 활용하는 명령어 ⋅

논리 세그먼트를 정의하거나 메모리 모델을 선택하거나 프로시저 만들거나 변수정의시 사용 ⋅

디렉티브는 어셈블러 구문으로서 인텔 명령어 집합과는 관계가 없다. ⋅

데이터 영역 프로시저의 시작

.data → , name PROC →

명령어(Instruction) ○

프로그램이 메모리에 탑재되어 실행될 때 프로세서에 의해 실행되는 문장 ⋅

명령어 데이터의 위치를 표시하는 하나의 식별자 Label - or

⋅ target:

mov ax, bx

명령어에 의하여 수행되는 동작을 식별하기 위한 단어 Mnemonic

-⋅

mov, add, sub...

명령어는 개까지 를 갖는데 이는 레지스터 메모리 피연산자 상수 Operand - 0~3 Operand , , , , ⋅

입출력 포트가 될 수 있다

or .

inc ax, mov count, bx

프로그램을 작성한 사람이 프로그램의 소스코드에 대한 설명 Comment

-⋅

COMMENT &

This line is a comment. &

프로그램의 어셈블링 링킹 그리고 실행

1-2. , ,

어셈블 링크 실행 주기- -○

Step1 ⋅

프로그래머는 문자 편집기를 사용하여 소스파일이라고 하는 아스키 문자 파일 생성 →

Step2 ⋅

어셈블러는 소스 파일을 읽어서 기계어 변환인 오브젝트 파일을 생성 오류시, 1단계로 이동 →

Step3 ⋅

링커는 오브젝트 파일을 읽고 링크 라이브러리 안에 있는 프로시저를 호출하는지 점검 후, →

(5)

Step4 ⋅

운영체제의 로더는 실행 파일을 메모리로 읽어 들이고 중앙처리장치를 프로그램의 시작 →

주소로 분기하게 하여 그 프로그램을 실행한다.

데이터 정의 1-3.

고유의 데이터 타입 ○

데이터 할당 ○

초기 설정 ⋅

에 문자 대입 value1 BYTE 'A' → value1 A

다중 초기 설정 ⋅

오프셋으로 구별 은 타입 수 만큼 증가 list BYTE 10, 'A', 30, 22h → (offset ) 문자열 설정

로 문자열의 끝을 구분 greeting1 BYTE "Good afternoon", 0 → NULL(0)

연산자를 이용한 설정 DUP

문자열이나 배열을 위한 공간 할당 시 유용

메모리 할당 후 으로 초기화 BYTE 20 DUP(0) → 20BYTE , 0

리틀 엔디언- (little endian) 순서 ○

아키텍쳐는 리틀 엔디언 방식을 따른다

Intel CPU .

변수의 가장 낮은 유효 바이트가 가장 낮은 주소에 저장되고 나머지는 다음의 연속적인 ⋅

메모리 위치에 저장.

일 경우 DWORD 12345678h

만약 메모리 오프셋 0에 위치해 있다면 78h가 첫 번째 바이트에 저장 →

타입

용도

BYTE 8비트 부호가 없는 정수 SBYTE 8비트 부호가 있는 정수

WORD 16비트 부호가 없는 정수 실세 주소 모드에서( Near 포인터로 사용될 수 있음) SWORD 16비트 부호가 있는 정수

DWORD 32비트 부호가 없는 정수 보호 모드에서( Near포인터로 사용될 수 있음) SDWORD 32비트 부호가 있는 정수

FWORD 48비트 정수 보호 모드에서( Far 포인터) QWORD 64비트 정수

TBYTE 80비트 (10바이트 정수)

(6)

심벌 상수 1-4.

심벌이 필요한 이유? ○

심벌을 사용함으로써 프로그램을 읽고 유지하기가 쉬움 ⋅

COUNT = 500 MOV ax, COUNT 프로그램 수정시 용이함. ⋅

가 번 쓰였을 경우 값 수정시 값만 바꿔주면 된다

COUNT 1000 COUNT .

심벌을 이용한 배열과 문자열의 크기 계산 ○

현재 위치 카운터 는 현재 오프셋 위치를 리턴함 이를 이용

$( ) . .

List BYTE 10, 20, 30, 40 ListSize = ($ - list)

디렉티브 EQU

심벌 이름을 정수 수식이나 임의의 문자와 연결 ⋅

PressKey EQU <"Press any key to continue...", 0> .data

prompt BYTE preekey

실습 1-5.

를 이용하여 문장의 글자 수를 계산하고 레지스터의 변화되는 값을 알아본다

LengthOf , .

소스코드 ⋅

TITLE LengthOf (hello.asm) ;program 제목과 파일명

INCLUDE \masm615\include\Irvine32.inc

어셈블러 파일을 텍스트파일에 복사한다

; Irvine32.inc .

.data ;date 세그먼트 시작

strlen BYTE "hello world" ;strlen 변수를 byte형으로 선언후 hello world로 초기화 시켜준다.

.code ;code 세그먼트 시작

main PROC ;main 프로시저 시작

mov eax,LENGTHOF strlen ;strlen의 문자열길이를 eax레지스터에 저장한다.

main ENDP ;main 프로시저의 끝

(7)

결과화면 ⋅

문자열의 길이가 이기 때문에 레지스터에 진수값인 로 저장이 된다

* 11 eax 16 B .

2

.

데이터 전송 주소지정 연산

,

,

데이터 전송 명령

2-1.

피연산자(Operand) 타입 ○

즉시값(Immediate), 레지스터(Register), 메모리(Memory)의 3개지 타입으로 구성. ⋅

직접 메모리 피연산자 ○

레지스터에 값을 이동 mov al, var1 → al var1

을 역참조하여 메모리의 내용을 가져와 레지스터에 이동 mov al, [00010400] → offset al

위치에서 를 더한곳의 값을 레지스터에 이동 mov al, [val1+5] → var1 offest 5 al

명령 MOV ○

소스 피연산자로부터 도착점 피연산자로 데이터를 이동 ⋅

MOV destination, source 피연산자 규칙 MOV

두 피연산자는 같은 크기여야 한다.

두 피연산자가 모두 메모리 피연산자일 수 없다. 는 도착점 피연산자가 될 수 없다

CS, EIP, IP .

피연산자 설명

r8 8비트 범용 레지스터 : AH, AL, BH, BL, CH, CL, DH, DL r16 16비트 범용 레지스터 : AX, BX, CX, DX, SI, DI, SP, BP

r32 32비트 범용 레지스터 : EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP reg 임의의 범용 레지스터

sreg 16비트 세그먼트 레지스터 : CS, DS, SS, ES, FS, GS imm 8, 16, 또는 32비트 즉시값

imm8 8비트 바이트 즉시값 imm16 16비트 워드 즉시값 imm32 32비트 더블워드 즉시값

(8)

즉시값은 세그먼트 레지스터로 이동될 수 없다. 명령

MOVZX ○

소스 피연산자를 도착점 피연산자로 복사하고 그 값을 16비트나 32비트로 확장한다. ⋅

확장된 부분은 0으로 채운다 단 부호가 없는 정수에만 사용된다. , . ⋅

MOV bx, 0A69Bh

MOV eax, bx ;EAX = 0000A69Bh

명령 MOVSX ○

와 같으며 확장된 부분을 로 채운다

MOVSX , 1 .

MOV bx, 0A69Bh

MOVSX eax, bx ;EAX = FFFFA69Bh

명령 XCHG ○

두 피연산자의 내용을 맞교환 한다. ⋅

xchg ax, bx

직접 오프셋 피연산자 ○

변수 이름에 변위를 더해 명시적으로 레이블링 되지 않은 메모리 위치를 엑세스 가능 ⋅

arrayB BYTE 10h, 20h, 30h, 40h, 50h mov al, [arrayB+1] ;AL = 20h

덧셈과 뺄셈 2-2.

명령 INC, DEC ○

증가 감소 명령은 단일 피연산자에 을 더하거나 을 빼준다

INC( ), DEC( ) 1 1 .

연산시 많이 쓰임 Loop Count . ⋅

myWord WORD 1000h inc myWord ;1001h dec myWord ;1000h

(9)

소스 피연산자를 동일 크기의 도착점 피연산자에 더한다. ⋅

ADD dest, source

소스는 연산에 의하여 변하지 않고 합이 도착점 피연산자에 저장된다. ⋅

명령 SUB ○

도착점 피연산자에서 소스 피연산자를 뺀다. ⋅

.data

var1 DWORD 3000h var2 DWORD 1000h .code

mov eax, var1

sub eax, var2 ;2000h

명령 NEG ○

수를 2의 보수를 취하는 것으로 그 수의 부호를 바꾼다. ⋅

NEG mem

연산의 플래그 영향 2-3.

어셈블리 언어에서는 각 연산 후에 상태 플래그를 점검하여 오버플로 오류를 제어할 수 있다. ○

제로(ZF)와 부호(SF) 플래그 ○

제로 flag는 계산 명령어의 도착점 피연산자가 0의 값을 가질 때 지정. ⋅

부호 플래그는 어떤값이 음수가 될 때 지정. ⋅

mov cx, 0

sub cx, 1 ;CX=-1, SF=1 add cx, 2 ;CX=1, SF=0

캐리(CF) 플래그 ○

가 부호 없는 연산을 수행할시 중요함

CPU .

부호 없는 덧셈의 결과가 매우 크거나 작을시 캐리 플래그가 지정된다. ⋅

최상위 비트(MSB)에서 발생한 캐리는 자동으로 캐리 플래그에 저장된다. ⋅

mov al, 0FFh

add al, 1 ;CF=1, AL=00

오버플로(OF) 플래그 ○

부호있는 연산에만 관계있음. ⋅

산술연산이 도착점 피연산자에 저장할 수 없는 부호 있는 수를 만들었을 경우에 지정 ⋅

⋅각 데이터 타입마다 가장 큰 숫자를 넘을 경우 1로 set된다 바이트의 경우( +127이상인 경우) mov al, +127

(10)

데이터 관련 연산자 및 디렉티브 2-4.

연산자 OFFSET

데이터 레이블의 오프셋을 리턴한다. ⋅

오프셋은 데이터 세그먼트의 시작으로부터 레이블까지의 거리를 바이트로 표현한다. ⋅

mov esi, OFFSET myArray+4

연산자 PTR

변수가 선언될때의 크기와는 다른 크기로 변수를 액세스 하고자 할 때 사용 ⋅

예를들어 더블워드 변수, myDouble의 하위 16비트만을 AX로 이동 ⋅

myDouble DWORD 12345678h mov ax, WORD PTR myDouble

연산자 LENGTHOF

레이블과 같은 줄에 나타나는 값에 의하여 정의된 배열의 요소 개수를 카운트함. ⋅

값은 array4 DWORD 1, 2, 3, 4 ; 4

연산자 SIZEOF

와 을 곱한 값을 리턴 LENGTHOF TYPE

intArray WORD 32 DUP (0) ;sizeof=64(32*2)

디렉티브 LABEL

레이블을 삽입할 수 있게 하며 그 레이블에 저장공간 할당 없이 크기 속성을 줄 수 있다. ⋅

데이터 세그먼트 내에 있는 기존의 변수에 다른 이름과 크기 속성을 주는 것이다. ⋅

간접 주소 지정 2-5.

간접 피연산자 ○

⋅배열을 처리하기 위한 실질적인 방법은 레지스터를 포인터로 사용하고 레지스터의 값을 다루는 것이고 이것을 간접 주소지정이라하며 주소를 지니는 레지스터는 간접 피연산자라 한다, . 대괄호로 둘러싸인 32비트 범용 레지스터(EAX, EBX, ECX, EDX, ESP, EBP, ESI, EDI)임 ⋅

.data

val1 BYTE 10h .code

는 의 오프셋을 포함한다 mov esi, OFFSET val1 ;esi val1 .

mov al, [esi] ;source에 간접 피연산자 사용지 ESI에 있는 포인터는 역참조 되고 바이트가 AL로 이동

(11)

배열 ○

간접 피연산자는 간접 피연산자의 값이 쉽게 수정될 수 있기 때문에 배열에 다룰 때 유용 ⋅

.data

arrayB BYTE 10h, 20h, 30h .code

mov esi, OFFSET arrayB

mov al, [esi] ;AL = 10h inc esi

mov al, [esi] ;AL = 20h

인덱스화된 피연산자 ○

유효주소를 만들기 위해 레지스터에 상수를 더한다. ⋅

임의의 32비트 범용 레지스터가 인덱스화된 피연산자로 쓰일 수 있다. ⋅

를 의미 arrayB[esi] → [arrayB + esi]

포인터 ○

다른 변수의 주소를 가지고 있는 변수를 말하며 배열과 데이터 구조체를 다룰때 많이 쓰임, . ⋅

계열 어셈블리는 와 두 종류의 포인터를 사용 Intel NEAR FAR

arrayB BYTE 10h, 20h, 30h, 40h

는 의 주소값을 지니고 있다 ptrB DWROD arrayB ;ptrB arrayB .

명령

2-6. JMP LOOP 이동 종류

무조건 이동(unconditional transfer) ⋅

프로그램은 모든 경우에 분기하며 새로운 주소에서 계속적인 실행이 일어나게 새로운 값이, 명령어 포인터로 탑재된다.

조건 이동(conditional transfer) ⋅

프로그램은 어떤 조건이 참이 될 때 이동하며 Intel 아키텍쳐는 조건 논리 구조를 만들기 위해 결합되는 광범위한 조건 이동 명령어를 제공한다.

는 와 플래그 레지스터의 내용을 근거로 참 거짓 조건을 해석함

CPU ECX / .

명령 JMP ○

코드 세그먼트 내 목표 위치로 무조건 이동한다. ⋅

위치는 어셈블러에 의하여 주소를 변환되는 코드 레이블에 의하여 식별되어야 함 ⋅

현재 프로시저 안에 있는 레이블로만 점프 가능 ⋅

16Bit Mode 32Bit Mode

포인터

NEAR 데이터 세그먼트의 시작부터

비트 오프셋 16

데이터 세그먼트의 시작부터 비트 오프셋

32

포인터

(12)

는 무조건이며 조건이 없을시 무한 반복 실행

JMP ,

⋅ top:

jmp top ;repeat the endless loop

명령 LOOP ○

문장의 블록을 특정 횟수 반복하는 쉬운 방법을 제공 ⋅

주로 ECX는 카운터로 많이 사용되며 루프가 반복될 때 매번 감소한다. ⋅

명령어는 단계로서 첫 번째는 에서 을 빼는 것이고 두 번째는 을 비교하는 것

LOOP 2 ECX 1 , 0

가 이 아니면 으로 식별되는 레이블로 점프하며 이면 점프가 일어나지

ECX 0 destination 0

않고 제어는 로프의 다음 명령어로 넘어간다, . L1:

inc ax loop L1

실습 2-7.

구구단중 2단부터 5단까지의 결과를 화면에 출력하라. ○

소스코드 ⋅

.data ;data 세그먼트 시작

valA DWORD 1 ;DWORD형 변수를 2개 선언후 1로 초기화

valB DWORD 1

.code ;code 세그먼트 시작

main PROC

mov ecx,4 ;루프카운터에 4를 대입한다.

L1: ;루프카운터에 의해 L1은 4번 반복한다.

push ecx ;ecx레지스터의 값을 Stack에 넣음으로서 다른 반복문을

다시 반복문으로 돌아올 수 있게 해준다

; L1 .

inc valA ;valA값을 1증가

mov valB, 1 ;valB에 1을 대입한다.

mov ecx,9 ;ecx루프카운터에 9를 대입한다.

L2: ;루프카운터에 의해 L2가 9번 반복된다.

mov eax,valA ;valA값을 eax레지스터에 대입한다.

call WriteDec ;eax레지스터 값을 출력한다.

mov al,'*' ;al레지스터에 값을 옮긴다* .

call WriteChar ;al레지스터값을 출력한다.

mov eax,valB ;valB값을 eax레지스터에 대입한다.

(13)

mov al,'=' ;al레지스터에 =를 대입한다.

call WriteChar ;=를 출력한다.

mov eax,valA ;valA값을 eax레지스터에 저장한다.

mul valB ;eax레지스터에 있는것과 valB값을 곱해준다.

call WriteDec ;eax레지스터에 있는값을 출력

call Crlf ;new line실행

inc valB ;valB값 1증가

loop L2 ;L2반복문의 끝

pop ecx ;기존 루프값을 꺼낸다.

call Crlf ;new line실행

loop L1 ;L1반복문의 끝

출력화면 ⋅

프로시저

3.

외부 라이브러리 링크 3-1.

링크 라이브러리는 기계어 코드로 어셈블된 프로시저를 갖고 있는 파일이다. ⋅

라이브러리에서 코드는 프로시저 상수 변수를 포함하는 하나이상의 소스파일로 시작한다, , . ⋅

소스 파일들은 오브젝트 파일로 어셈블되고 그 오브젝트 파일은 라이브러리에 삽입된다. ⋅

링커 명령어로 오브젝트 파일과 기타 링크 라이브러리를 합친다. ⋅

(14)

제공 링크 라이브러리 3-2. MASM

링크 라이브러리에 있는 프로시저 Irvine32

콘솔을 지우고 커서를 위의 왼쪽에 위치시키라

Clrscr .

Crlf 표준 출력에 줄의 끝임을 출력하라.

Delay 특정한 n밀리초 동안 프로그램 실행을 멈추라. 메모리 블록을 표준 출력에 진수로 쓰라

DumpMem 16 .

레지스터를 DumpRegs EAX, EBX, ECX, EDX, ESI, EBP, ESP, EFLAGS, EIP 16

진수로 표시하라 또한 캐리 부호 제로 오버플로 플래그를 표시하라. , , , . GetCommandtail 프로그램의 명령어 인수를 바이트의 배열로 복사하라.

시 이후로 경과된 시간을 미리초로 리턴하라

GetMseconds 0 .

콘솔 상에 커서를 특정한 행과 열에 위치하게 하라 Gotoxy

부터 까지 비트 무작위 정수를 발생시키라 Random32 0 FFFFFFFFh 32 . Randomize 유일한 값을 사용하여 무작위 수 발생기를 시드하라. RandomRange 특정한 범위 안에 있는 무작위 정수를 발생시키라. ReadChar 표준 입력으로부터 문자 하나를 읽으라.

ReadHex Enter키에 의하여 종료되는 32비트 16진 정수를 표준 입력으로부터 읽으라. 키에 의하여 종료되는 비트 부호있는 진수를 표준입력으로부터

ReadInt Enter 32 10

읽으라.

ReadString Enter키에 의하여 종료되는 문자열을 표준 입력으로부터 읽으라. SetTextColor 콘솔에 출력되는 모든 문자의 전경색과 배경색을 지정하라. WaitMsg 메시지를 출력하고 Enter키가 눌러질 때까지 기다리라.

WriteBin 부호가 없는 32비트 정수를 표준 출력에 아스키 2진 포맷으로 쓰라. 하나의 문자를 표준 출력에 쓰라

WriteChar .

부호가 없는 비트 정수를 표준 출력에 진 포맷으로 쓰라

WriteDex 32 10 .

부호가 없는 비트 정수를 표준 출력에 진 포맷으로 쓰라

WriteHex 32 16 .

부호가 있는 비트 정수를 표준 출력에 진 포맷으로 쓰라

WriteInt 32 10 .

널 문자로 끝나는 문자열을 표준 출력에 쓰라

WriteString .

스택 동작 3-3.

데이터 구조 Stack

스택은 LIFO(last-in, first-out)구조로서 새로운 값이 스택의 맨 위에 추가되고 기존의 값은, ⋅

맨 위에서부터 빠져 나온다는 원리

실행 시의 스택 ○

실행시의 스택은 두 개의 레지스터 SS와 ESP를 사용하여 CPU가 직접 관리하는 메모리 배열 ⋅

레지스터는 세그먼트 서술자를 갖으며 이것은 사용자 프로그램이 수정할 수 없다

SS , .

스택 포인터 레지스터(ESP)는 마지막으로 푸시된 정수를 가리킨다. ⋅

(15)

푸시(push)동작 ○

⋅푸시동작은 스택 포인터를 4감소시키며(32비트인 경우 새로운 값을 스택 포인터가) 가리키는 저장위치에 복사

팝(Pop)동작 ○

팝 동작은 스택으로부터 값을 제거하고 그 값을 레지스터나 변수에 놓는다. ⋅

스택으로부터 팝된 후 스택 포인터는 스택의 그 다음 높은 저장위치를 가리킴 ⋅

의 사용 Stack

레지스터가 하나 이상의 목적으로 사용될 때 레지스터를 저장하는 임시적인 영역으로 ⋅

편리하게 사용된다 레지스터가 수정된 후에 원래의 값으로 복원될 수 있음. 명령이 실행되었을 때 는 현재 프로시저의 리턴 주소를 스택에 저장

CALL CPU

프로시저를 호출할 때 인수(argument)를 전달 이것들이 스택에 푸시될 수 있다. . ⋅

프로시저 안의 지역 변수들은 스택 위에 생성되며 프로시저가 끝나면 사라진다. ⋅

프로시저의 정의 및 사용 3-4.

프로시저의 정의 ○

언어의 함수 개념이랑 비슷 high-level

비공식적으로 프로시저는 리턴 문으로 끝나는 문장들의 블록으로 정의 ⋅

과 디렉티브를 사용하여 선언 PROC ENDP

시작 프로시저가 아닌 다른 프로시저를 만들 때 RET문으로 끝내라. ⋅

를 프로시저를 호출한 위치로 리턴하게 함

(cpu .)

(16)

sample PROC .

. ret

sample ENDP

과 명령 CALL RET ○

명령은 프로세서가 새로운 메모리 위치에서 시작하게끔 조정하여 프로시저를 호출한다

CALL .

프로시저는 프로시저를 호출한 위치로 프로세서를 돌아오게 하기 위하여 RET명령을 사용 ⋅

기계적으로 볼 경우 CALL명령은 리턴 주소를 스택에 놓고 호출되는 프로시저의 주소를 ⋅

명령어 포인터에 놓는다.

그 프로시저가 리턴될 준비가 되면 RET명령은 스택에서 리턴 주소를 명령어 포인터로 팝함 ⋅

는 항상 명령어 포인터 레지스터인 가 가리키는 메모리 위치의 명령어를 실행함

cpu EIP .

main PROC

call Mysub ;00000020 mov eax, ebx ;00000025

Mysub PROC

mov eax, edx ;00000040 .

.

Mysub ENDP

의 첫 번째 실행 명령어가 오프셋 에 있다고 하면 명령이 실행

Mysub 00000040 , CALL

되었을 때 호출문의 다음주소(00000025)는 스택에 푸시되고 Mysub주소가 EIP로 탑재. 에 있는 모든 명령은 를 만날 때까지 실행되며 명령이 실행되면 스택에서

Mysub RET RET

가 가리키는 값이 로 팝된다

ESP EIP .

실습 3-5.

구현 Greatest Common Divisor ○

두 정수의 최대공약수(GCD)를 구하는 함수를 Recursive Ver.으로 작성 ⋅

입력받은 두 정수를 나머지 나눗셈(%)을 하여 나온 값이 0보다 클 동안 반복 ⋅

를 연산하는 부분은 반드시 로 작성 GCD User Proc

소스코드 ⋅

(17)

;_________________________________________________________data .data

inputMsg1 BYTE "Enter the First number : ",0 inputMsg2 BYTE "Enter the Second number : ",0 resultMsg BYTE " GCD : ",0

valL DWORD ? ; 첫 번째 입력값 || 큰 변수 valS DWORD ? ; 두 번째 입력값 || 작은 변수

GCD DWORD 1 ; GCD 값이 저장될 변수

;---code .code

insert PROC

mov edx,OFFSET inputMsg1 ; 첫 번째 숫자 입력 call WriteString

call ReadInt

mov valL,eax ; 변수 valL에 첫 번째 입력값 저장

mov edx,OFFSET inputMsg2 ; 두 번째 숫자 입력 call WriteString

call ReadInt

mov valS,eax ; 변수 valS에 두 번째 입력값 저장

ret

insert ENDP

;---gcd proc

gcdMul PROC

mov eax,valL

cmp eax,valS ; valL 와 valS 대소 비교 jae DiL

mov eax,valL

xchg eax,valS ; valS가 valL보다 크므로 스위치

mov valL,eax

DiL:

mov edx,0 ; 나눗셈전 edx 0으로 초기화 mov eax,valL

(18)

je R1

mov ebx,valL

sub ebx,valS ; 큰수에서 작은 수를 뺌

cmp valS,ebx ; 작은수와 큰수와 작은 수의 차를 비 교

mov eax,valS mov valL,eax

mov valS,ebx

mov eax,valL cmp eax,valS jae DiL

mov eax,valL

xchg eax,valS ; 변수 대소 비교 후 체인지 mov valL,eax

call gcdMul ; 재귀 함수 구현

R1:

mov edx,OFFSET resultMsg call WriteString

mov eax,GCD ; 나눠지는 수가 없을 시 소수 초기( ) 값 1출력

mul valS

call WriteDec ; 결과 값 출력 call Crlf

ret gcdMul ENDP

;---main PROC main PROC

call insert call gcdMul exit

main ENDP

(19)

결과 화면 ⋅

조건부 처리

4.

부울 및 비교 명령 4-1.

부울 명령 ○

명령 AND ○

두 개의 피연산자에서 매칭되는 비트 사이에 부울 AND연산을 하고 그 결과를 도착점 ⋅

피연산자에 놓는다. AND destination, source

명령은 종종 선택된 비트를 해제하고 나머지를 유지할 때 사용된다

AND .

명령은 항상 오퍼플로 플래그 와 캐리 플래그 를 해제한다

AND (OF) (CF) .

명령 OR ○

두개의 피연산자에서 매칭되는 비트사이에 부울 OR 연산을 하고 그 결과를 도착점 ⋅

피연산자에 놓는다. OR destination, source

명령은 종종 선택된 비트를 지정하고 다른 것을 유지할 때 사용한다

OR .

명령은 항상 캐리와 오버플로 플래그를 해제한다

OR .

연산 설명

AND 소스 피연산자와 도착점 피연산자 사이의 부울 AND 연산

OR 소스 피연산자와 도착점 피연산자 사이의 부울 OR 연산

XOR 소스 피연산자와 도착점 피연산자 사이의 부울 XOR연산

NOT 도착점 피연산자에 부울 NOT 연산

TEST 소스 피연산자와 도착점 피연산자 사이의 묵시적 부울 AND연산을 수행하여 중앙처리장치의 플래그를 적절히 지정

BT, BTC, BTR, BTE

(20)

명령 XOR ○

두 개의 피연산자에서 매칭되는 비트 사이에 부울 배타적 OR연산을 하고 그 결과를 ⋅

피연산자에 놓는다. XOR destination, source

명령은 와 와 같은 피연산자 조합을 사용한다

XOR AND OR .

의 특별한 점은 동일한 피연산자를 두 번 적용하면 그 자체가 된다

XOR .

명령은 항상 캐리와 오버플로 플래그를 해제한다

XOR .

명령 NOT ○

피연산자의 모든 비트를 바꾸고 그 결과는, 1의 보수(one's complement)라 한다. ⋅

어떤 플래그도 영향을 받지 않는다. ⋅

mov al, 11110000b

not al ;AL=00001111b

명령 TEST ○

두 피연산자 사이에 매칭되는 비트에 대하여 묵시적 AND연산을 수행하고 결과에 따라서 ⋅

플래그를 지정한다.

와 차이점은 도착점 피연산자를 수정하지 않는다

AND .

명령은 항상 오버플로 플래그와 캐리 플래그를 해제한다

TEST .

부호 제로 패리티 플래그는, , AND명령에서와 동일하게 수정된다. ⋅

명령 CMP ○

도착점 피연산자로부터 소스 피연산자를 묵시적으로 빼며 어떤 피연산자도 수정되지 않는다, . ⋅

CMP destination, source

명령은 오버플로 부호 제로 캐리 보조캐리 패리티 플래그를 명령이 사용되었다고

CMP , , , , , SUB

했을 때의 도착점 피연산자 값에 따라서 변화시킨다.

조건부 점프 4-2.

조건부 실행 순서 ○

등의 연산으로 중앙처리장치 플래그를 수정한다

CMP, AND, SUB .

조건부 점프 명령어가 플래그를 테스트하여 새로운 주소로 분기한다. ⋅

CMP leftOp, rightOp

CMP Results ZF CF Flags

destination < source 0 1 SF OF≠

destination > source 0 0 SF=OF

(21)

cmp al, 0

jz L1 ;jump if ZF=1 .

L1:

특정한 플래그 값에 근거한 점프 ○

등호에 근거한 점프 ○

부호가 없는 비교 ○

니모닉 설명 플래그

JZ Jump if zero ZF=1

JNZ Jump if not zero ZF=0

JC Jump if carry CF=1

JNC Jump if not carry CF=0

JO Jump if overflow OF=1

JNO Jump if not overflow OF=0

JS Jump if signed SF=1

JNS Jump if not signed SF=0 JP Jump if parity(even) PF=1 JNP Jump if not parity(odd) PF=0

니모닉 설명

JE jump if equal(leftOp=rightOp) JNE jump if not equal(leftOp rightOp)≠ JCXZ jump if CX=0

JECXZ jump if ECX=0

니모닉 설명

JA jump if above(if leftOp>rightOp)

JNBE jump if not below or equal(same as JA)

JAE jump if above or equal(if leftOp>=rightOp)

JNB jump if not below(same as JAE)

JB jump if below(if leftOp<rightOp)

JNAE jump if not above or equal(same as JB)

JBE jump if below or equal(if leftOp<=rightOp)

(22)

부호가 있는 비교 ○

조건부 루프 명령 4-3.

명령 LOOPZ(loop if not zero) ○

제로 플래그가 지정되어 있고 부호없는 값 ECX가 0보다 큰 경우 루프를 계속 실행시킴 ⋅

LOOPZ destination

명령 LOOPE(loop if not equal) ○

와 동일한 명령이며 배열에서 첫 번째 숫자를 비교한 후 루프를 반복한다

LOOPZ .

ECX=ECX-1

if ECX>0 and ZF=0, jump to destination

조건부 구조 4-4.

블록 구조의 IF문 ○

대부분의 고급 언어에서, IF문은 부울 수식이며 그 수식이 참이었을 때 수행되는 것과 ⋅

거짓이었을 때 수행되는 두 개의 문이 따라 나온다. 기본 IF (Java/c++)문

if(op1 == op2) {

x=1, y=2; }

기본 IF (문 어셈블리) ⋅

mov eax, op1

cmp eax, op2 ;compare EAX to op2 je L1 ;jump if equal to L1 jmp L2 ;otherwise, jump to L2 L1:

mov x,1 mov y,2 L2:

니모닉 설명

JG jump if greater(if leftOp>rightOp)

JNLE jump if not less than or equal(same as JG)

JGE jump if greater than or equal(if leftOp>=rightOp)

JNL jump if not less(same as JGE)

JL jump if less(if leftOp<rightOp)

JNGE jump if not greater than or equal(same as JL)

JLE jump if less than or equal(if leftOp<=rightOp)

(23)

논리 AND연산자(Java/c++) ⋅

if(a1>b1) AND (b1>c1) { x=1; }

논리 AND연산자 어셈블리( ) ⋅

cmp a1, b1 ;first expression ja L1

jmp next L1:

cmp b1, c1 ;second expression ja L2

jmp next

L2: ;both are true mov x,1 ;set x to 1 next:

논리 OR연산자(Java/c++) ⋅

if(a1>b1) OR (b1>c1) x=1;

논리 OR연산자 어셈블리( ) ⋅

cmp a1, b1 ;1: compare AL to BL

ja L1 ;if true, skip second expression cmp b1, c1 ;2: compare BL to CL

jbe next ;false: skip next statement L1:mov x,1 ;true: set x=1

next:

루프 WHILE ○

루프

WHILE (Java/c++) ⋅

while(val1 < val2) {

val1++, val2--; }

루프 어셈블리 WHILE ( ) ⋅

mov eax, val1 ;copy variable to eax while:

cmp eax, val2 ;if not(val1<val2) jnl endwhile ;exit the loop inc eax ;val1++; dec val2 ;val2--;

jmp while ;repeat the loop endwhile:

(24)

SWITCH CASE ○

어셈블리 Switch case( ) ⋅

.data

CaseTable BYTE 'A' ;lookup value

DWORD Process_A ;address of procedure BYTE 'B'

DWORD Process_B (etc.)

실습 4-5.

에 대해서 프로그램을 코딩하고 를 이용해서 과정을 상세히 이해하고

n! , Debugger Stack ,

개 이상의 를 인자값으로 받는 함수가 호출될 때 어떻게 스택에 저장되는지 5 argument

디버거를 통해 알아보시오.

소스코드 ⋅

TITLE Calculating a Factorial (Fact.asm)

; This program uses recursion to calculate the ; factorial of an integer.

; Last update: 09/05/13

INCLUDE \masm615\include\Irvine32.inc

함수를 선언해준다 와 는 짝이다 Factorial PROTO, ; .(invoke proto .)

a1:DWORD, ;인자값을 개 받는다5 . b1:DWORD,

c1:DWORD, d1:DWORD, e1:DWORD

.data

num1 DWORD 12 num2 DWORD 1 num3 DWORD 2 num4 DWORD 3 num5 DWORD 4

.code main PROC

(25)

를 레지스터에 저장한다 mov eax, num1 ;12 eax .

INVOKE Factorial, ;Factorial함수를 호출하면서 인자값으로 개를 넘긴다5 . num1,

num2, num3, num4, num5

함수호출이 모두 끝날 경우 이곳으로 리턴되 실행된다

ReturnMain: ; .

call WriteDec ;eax레지스터의 값을 출력한다. call Crlf

exit main ENDP

프로시저 Factorial PROC, ;Factorial

a1:DWORD, ;인자값으로 넘겨받은 값을 DWORD형으로 b1:DWORD, ;차례대로 a1~a5변수에 대입한다. c1:DWORD,

d1:DWORD, e1:DWORD

위치를 레지스터에 저장 mov ebp,esp ;stack point ebp

mov eax,[ebp+8] ;현재 가리키는 주소값에서 을 더하면 그위치의 값을8 에 저장한다

;eax .

값에 을 더하게 되면 주소값과 값을 지나 ;EBP 8 return ebp

처음에 한 값이 저장된다 ; push 12 . cmp eax,0 ;0과 값을 비교한다.

ja L1 ;eax레지스터의 값이 클 경우 L1으로 jump

mov eax,1 ;같을 경우 eax레지스터에 을 대입하고1 L2로 jump jmp L2

값을 감소시킨다 L1: dec eax ;eax 1 .

INVOKE Factorial, ;Factorial함수를 호출한다 재귀 호출.( ) 번째 인자값으로 레지스터값을 넘겨준다

eax, ;1 eax .

(26)

; Instructions from this point on execute when each ; recursive call returns.

재귀 함수가 리턴됬을 경우 실행된다

ReturnFact: ; .

mov ebx,[ebp+8] ; get n mul ebx ;ax = ax * bx

L2: ret 4 ;stack을 clear해준다. Factorial ENDP

END main

결과 화면 ⋅

결과 화면 <12! >

디버깅 과정 ⋅

디버거를 이용할시 어셈블러에 의해 생성된 실행파일을 Visual c++아이콘에 드래그 해주면 디버 거를 할 수 있다. F10을 누르게 되면 어셈블리 코드를 볼 수 있으며 좀 더 자세히 접근할시,

를 이용할 수 있다 BreakPoint .

를 이용한 디버거 화면 이용 <Visual C++ > <Visual C++ 2008 >

을 순차적으로 누르게 되면 다음 줄 어셈블리 코드가 실행이 된다 이때 값이 변하는 레지스

F10 .

(27)

포인터이다 따라서. ESP레지스터에 들어있는 주소값을 Memory에 입력하게 되면 거기에 해당되 는 값을 볼 수가 있다.

메모리를 참조할 경우 Memory의 주소값은 16진수로 되있기떄문에 주소값을 입력할 경우 앞에 를 붙여 준다 빨간색 동그라미는 이며 노란색 화살표는 이번에 실행될 코드이다

0x . ( BreakPoint .)

(28)

앞에 본 화면에서 번 더 실행 < 2 >

의 의 주소를 참고하면 값이 있고 칸뒤에 이 또 칸뒤에 가 저장 Memory Ox0012FFC 02 4 03 , 4 04

돼있다.

이 말은 num5, num3까지가 push돼있다 따라서 함수호출시 인자값을 넘길 경우 오른쪽에 있는. 값부터 push된다는 것을 알 수 있다.

또한, num의 변수는 DWORD로 선언되어 있기 때문에, 4Byte의 Memory를 차지하게 된다 따. 라서 1개블럭(00)당 1Byte이기 때문에 총 4블럭을 차지하게 된다 따라서 인텔 프로세서는 리틀. 엔디언 방식이기 때문에 변수의 가장 낮은 유효바이트가 가장 낮은 주소에 저장됨 - (Little endian)

을 Memory창에서 확인할 수 있다.

정수연산

5.

시프트와 회전 명령 5-1.

시프트 ○

시프트란 피연산자 안에서 비트를 좌우로 이동하는 것을 의미 ⋅

이동시 오버플로와 캐리 플래그에 영향을 줌 ⋅

좌시프트

SHL SHR 우시프트 SAL 산술 좌시프트 산술 우시프트

SAR ROL 좌회전 ROR 우회전

캐리 포함 좌회전

RCL RCR 캐리 포함 우회전 SHLD 더블 좌시프트 더블 우시프트

SHRD

논리 시프트와 산술 시프트 ○

논리 시프트(logical shift)는 새로운 비트 위치를 0으로 채운다. ⋅

산술 시프트(Arithmetic shift)는 새로 만들어지는 비트 위치는 원래 수의 부호 비트 값으로 ⋅

채운다.

좌시프트 명령 SHL( ) ○

도착점 피연산자의 최하위 비트를 0으로 채우는 논리 좌시프트 동작을 수행 ⋅

가장 상위 비트는 캐리 플래그로 옮겨 가고 캐리 플래그에 있는 비트는 손실된다, . ⋅

(29)

우시프트 명령 SHR( ) ○

도착점 피연산자에 대해 논리 우시프트 연산을 수행하여 최상위 비트를, 0으로 치환한다. ⋅

최하위 비트는 캐리 플래그로 복사되고 캐리 플래그에 있던 비트는 손실된다, . ⋅

좌회전 명령 ROL( ) ○

각 비트를 왼쪽으로 시프트 하며 최상위 비트가 캐리 플래그와 최하위 비트로 복사 된다, . ⋅

회전을 함으로써 비트 손실이 없다. ⋅

을 이용해서 한 바이트의 상위 비트 비트 와 하위 비트 비트 을 교환 가능

ROL , 4 ( 4~7) 4 ( 0~3)

우회전 명령 ROR( ) ○

각 비트를 오른쪽으로 시프트한다. ⋅

최하위 비트를 캐리 플래그와 최상위 비트에 동시에 복사한다. ⋅

명령 포맷은 SHL과 동일 ⋅

곱셈과 나눗셈 명령 5-2.

명령 MUL ○

에 비트 피연산자를 곱하는 명령어 이다 AL, AX, EAX 8, 16, 32 . ⋅

표는 승수의 크기에 따른 디폴트 피연산자와 곱셈결과를 보여준다. ⋅

곱셈결과를 저장하는 레지스터는 피승수와 승수 크기의 2배이어서 오버플로가 생기지, ⋅

않도록 해야한다.

곱셈결과의 상위 절반이 0이 아니면 캐리와 오버플로 플래그가 영향을 받는다. ⋅

mov al, 5h mov b1, 10h

mul b1 ;CF=0

명령 IMUL ○

부호 있는 곱셈 명령은 부호 있는 정수 곱셈을 수행한다

IMUL( ) .

명령과 동일한 구문과 피연산자를 가지며 차이점은 곱셈의 부호를 유지한다

MUL , .

은 곱셈 결과의 상위 부분이 하위 부분의 부호 확장이 아니면 캐리 플래그와 오버플로 IMUL

플래그를 설정한다.

mov ax, 48 mov bx, 4

피승수 승수 곱셈결과

AL r/m8 AX

AX r/m16 DX:AX

(30)

imul bx ; DX:AX=000000C0h, OF=0

명령 DIV ○

부호 없는 나눗셈 명령은 부호 없는 정수에 대해 비트 나눗셈을 수행함

DIV( ) 8, 16, 32 .

단일 피연산자만 나태내며 그 피연산자는 제수가 된다, . ⋅

mov ax, 0083h ;dividend mov bl, 2 ;divisor

div bl ;AL=41h, AH=01h

나눗셈 오버플로 ○

나눗셈에서 너무 큰 몫이 만들어져서 도착점 피연산자에 모두 들어갈 수 없으면 나눗셈, ⋅

오버플로(divide overflow)조건이 발생한다.

이는 CPU인터럽트를 발생시키고 현재 프로그램을 중단시킨다, . ⋅

mov ax, 1000h

mov bl, 10h

div bl ;AL cannot hold 100h

⋅위 소스 실행 결과 생긴 몫(100h)이 AL레지스터에 저장될 수 없으므로 나눗셈 오버플로 발생

고급프로시저

6.

지역변수

6-1. (local variable) 지역 변수란?

단일 프로시저 안에서 생성 사용 소멸되는 변수이다, , . ⋅

지역 변수에 대한 제한된 엑세스는 디버깅할 때 도움을 준다 단지 몇몇 제한된 프로그램.( ⋅

문장들만이 변수를 수정할 수 있기 때문.)

지역 변수들은 메모리를 효과적으로 사용한다 지역 변수들의 저장 공간은 해제될 수 있고.( , ⋅

새로운 변수들이 그 저장공간을 사용할 수 있기 때문.)

같은 변수 이름은 이름 충돌을 일으키지 않은 한 두 개 또는 그이상의 프로시저들에서, ⋅

나타낼 수 있다.

지역 변수들은 실행 시 스택에서 생성한다. ⋅

디렉티브 LOCAL

디렉티브는 하나의 프로시저 내부에서 하나 또는 그 이상의 지역 변수들을 선언한다

LOCAL .

디렉티브 바로 다음 행에 위치해야 한다

PROC .

지역 변수 사용시 어셈블러에 의해 코드 생성, ⋅

피제수 제수 나머지

AX r/m8 AL AH

DX:AX r/m16 AX DX

(31)

BubbleSort PROC

LOCAL temp : DWORD, SwapFlag : BYTE ret

의 코드는 BubbleSort ENDP

BubbleSort: push ebp mov ebp, esp

add esp, 0FFFFFFF8h mov esp, ebp

구조 pop ebp <stack >

으로 생성된다

ret .

지역 변수로 어떤 크기의 배열을 생성하려고 하면 반드시 프로그램을 어셈블하기 전에, ⋅

충분한 스택 공간을 따로 할당(allocate)해야 한다.

스택 매개변수 6-2.

와 의 차이 argument parameter

인수(argument)는 호출하는 프로그램에 의해 프로시저로 전달되는 값이다. ⋅

매개변수(parameter)는 호출된 프로시저가 받는 값을 말한다. ⋅

디렉티브 INVOKE

디렉티브는 다중 인수를 전달할 수 있게 하는 의 명령에 대한 보다 더

INVOKE Intel CALL

강력한 대안이다.

INVOKE procedureName [,argumenList]

는 프로시저로 전달되는 인수들이 콤마로 분리된 일람이다

argumenList .

는 인수들의 일람을 포함하지 않는다

CALL .

는 임의 개수의 인수를 허용하며 각 인수들은 여러 소스 코드 행에 걸쳐

INVOKE ,

나타날 수 있다.

와 함께 사용하는 인수의 유형 INVOKE

연산자는 디렉티브를 가지고 프로시저를 호출할 때 포인터를 전달하기 위해

ADDR INVOKE ,

사용된다 프로시저 인수로 주소를 전달하는 것을 참조에 의한 전달. (passing by reference)

유형

즉시값 10, 3000h, OFFSET myList, TYPE array

정수 수식 (10*20), COUNT

변수명 myList, array, myWord, myDword

주소 수식 [myList+2], [ebx+esi]

레지스터 명 eax, bl, edi

(32)

라한다.

INVOKE FillArray, ADDR myArray

아래 코드는 Swap프로시저를 호출하면서 더블워드 배열에 있는 처음 두 원소릐 주소를, ⋅

전달하는 방법이다. .data

Array DWORD 20 DUP(?) .code

...

INVOKE Swap, ADDR Array ADDR Array+4

디렉티브 PROC

디렉티브는 매개변수 알람과 프로시저 이름을 선언한다

PROC .

label PROC, parameter_1, parameter_n

디렉티브 PROTO

디렉티브는 존재하는 프로시저의 프로토타입 을 만든다

PROTO (prototype) .

프로토타입은 프로시저의 이름과 매개변수 일람을 선언한다. ⋅

프로토타입은 프로시저를 정의하기 전에 호출할 수 있게 해준다. ⋅

은 문장에 의해 호출되는 각 프로시저에 대해 프로토타입을 요구한다

MASM INVOKE .

주의할 사항은 PROTO는 반드시 INVOKE 이전에 나타나야 한다. ⋅

프로시저 순서 ⋅

PROTO mySub ;procedure prototype INVOKE mySub ;procedure call

mySub PROC ;procedure implementation .

. mySub ENDP

단 프로시저 구현은, INVOKE문장 이전에 나올 수 있다 이 경우. , PRO는 프로토타입 역할임 ⋅

값에 의한 전달(passing by value) ○

변수 값의 복사본이 프로시저로 절달될 때 이것을 값에 의한 전달이라 한다, . ⋅

일반적으로 호출된 프로시저에 의해 값이 변하지 않도록 인수들을 값에 의해 전달 한다, . ⋅

변수의 복사본은 호출하는 프로그램에 의해 스택에 푸시되며 호출된 프로시저는 스택, ⋅

으로부터 값을 가져와서 그 값을 이용한다.

프로시저가 매개 변수를 변경하더라도 호출하는 프로그램에 있는 대응 되는 인수 값에, ⋅

액세스할 수 없다. .data

(33)

.code main PROC

INVOKE Sub1, myData exit

main ENDP

Sub1 PROC someDate:WORD mov someData, 0

ret Sub1 ENDP

참조에 의한 전달(passing by reference) ○

변수의 주소가 프로시저로 전달될 때 이것을 참조에 의한 전달 이라한다, . ⋅

호출된 프로시저는 주어진 주소를 통해 변수의 내용을 변경할 수 있다. ⋅

프로시저가 변수를 변경할 것으로 예상되는 경우에만 쓰는 것이 좋다, . ⋅

.data

myData WORD 1000h .code

main PROC

INVOKE Sub2, ADDR myData ;pass by reference exit

main ENDP

Sub2 PROC dataPTr:PTR WORD

mov esi, dataPtr ;get the address

mov WORD PTR[esi], 0 ;dereference, assign zero Sub2 ENDP

문자열과 배열

7.

문자열 프리미티브 명령 7-1.

문자열 프리미티브 ○

바이트 워드 더블워드의 배열 처리를 위한, , Intel 명령 집합에는 5개의 그룹이 있으며 이를, ⋅

문자열 프미리티브라고 하지만 문자 배열로만 국한되진 않는다, .

문자열 명령어는 메모리를 참조하기 위해 ESI, EDI 레지스터를 참조한다. ⋅

는 유일하게 단일 메모리 피연산자를 사용하여 문자열과 배열의 처리에 특히 유용

ESI, EDI ,

보호모드 에서는 ESI는 자동적으로 DS가 가리키는 세그먼트에서의 오프셋이 되고, EDI는 ⋅

자동적으로 ES가 가리키는 세그먼트 내의 오프셋이 된다. 는 항상 같은 값으로 설정되고 이를 변경할 수 없다

DS, ES , .

(34)

문자열 프리미티브 명령 ⋅

MOVSB, MOVSW, MOVSD ○

세 명령은 ESI가 가리키는 메모리 위치에서 EDI가 가리키는 메모리 위치로 데이터를 복사함 ⋅

두 개의 레지스터들은 자동적으로 방향 플래그값에 의해 증가 or 감소한다. ⋅

바이트들의 이동 복사 감소 MOVSB - ( ), ESI/EDI 1 ⋅

워드들의 이동 복사 감소 MOVSW - ( ), ESI/EDI 2

더블워드들의 이동 복사 감소 MOVSD - ( ), ESI/EDI 4

CMPSB, CMPSW, CMPSD ○

세 명령은 각각 ESI가 가리키는 메모리 피연산자와 EDI가 가리키는 메모리 피연산자를 비교 ⋅

방향 플래그에 의해 ESI, EDI값이 증가 또는 감소한다. ⋅ 바이트 비교 CMPSB -⋅ 워드 비교 CMPSW -더블워드 비교 CMPSD

-STOSB, STOSW, STOSD ○

세 명령은 각각 AL/AX/EAX의 내용을 EDI가 가리키는 오프셋 위치의 메모리에 저장함. ⋅

는 방향 플래그에 의해 증가 감소 된다

EDI or .

LODSB, LODSW, LODSD ○

세 명령은 ESI가 가리키는 메모리에서 바이트나 워드를 읽어 AL/AX/EAX에 저장 ⋅

는 방향 플래그에 의해 증가 감소 된다

ESI or .

선택된 문자열 프로시저 실습

7-2. ( )

Str_concat ○

문자열의 끝에 문자열을 연결하는 프로시저를 작성하라 target source Str_concat . 이 프로시저가 호출되기 전에 target문자열 내에 충분한 공간이 필요하다. source와

문자열에 대한 포인터를 전달하라

target .

명령어 설명

MOVSB, MOVSW, MOVSD

CMPSB, CMPSW, CMPSD

SCASB, SCASW, SCASD

STOSB, STOSW, STOSD

LODSB, LODSW, LODSD

문자열 데이터 이동 : 한 메모리 위치로부터 다른 곳으로 정수를 복사

문자열 비교 : 두 개의 메모리 값들을 비교

문자열 검색 : 정수와 메모리의 내용 비교

문자열 데이터 저장 : 메모리에 정수 저장

(35)

소스코드 ⋅

TITLE Str_concat

INCLUDE \masm615\include\Irvine32.inc

Str_concat PROTO, ;str_concat 프로시저 PROTO선언 ta : PTR BYTE,

so : PTR BYTE

.data

target BYTE "ABCDE",10 DUP(0) ;source의 문자열을 target문자열에 붙인다. source BYTE "FGH",0

.code

;================================================main main PROC ;main함수 시작

mov edx,OFFSET target ;target문자열 출력 call WriteString

call crlf

mov edx,OFFSET source ;source문자열 출력 call WriteString

call crlf

INVOKE Str_concat, ADDR target, ADDR source

을 호출하면서 두 문자열의 주소값을 넘긴다

;Str_concat .

mov edx,OFFSET target ;target문자열 출력 call WriteString

call crlf

exit

main ENDP ;main함수 끝.

;==============================================str Proc

Str_concat PROC, ;파라미터로 2개의 문자열의 주소값을 받는다. ta : PTR BYTE,

so : PTR BYTE

.data

(36)

strlenso DWORD ?

.code

mov esi, ta ;ta, so의 시작주소값을 esi, edx에 각각 대입한다. mov edx, so

mov ebx, [esi] ;esi가 가리키는 곳의 값을 ebx레지스터에 대입한다.

mov eax, 0 ;eax를 0으로 초기화시킨다 여기서. eax문자열의 길이를 계산 L2:

cmp ebx, 0 ;ebx에 있는값과 0과 비교한다.

je L3 ;같으면 L3로 이동하고 다를시 아래줄 실행 inc esi ;esi와 eax값을 1씩 증가시킨다.

inc eax

mov ebx, [esi] ;증가된 주소값의 값을 ebx대입한다. jmp L2 ;L2로 점프

L3:

mov strlenta, eax ;Count된 eax값을 strlenta에 대입한다.(target의 문자열 길이)

mov ebx, [edx] ;source의 문자열 길이도 구한다. mov eax, 0

L4:

cmp ebx, 0 je L5

inc edx inc eax

mov ebx, [edx] jmp L4

L5:

mov strlenso, eax

mov esi, ta ;esi와 edx가 가리키고 있는 주소값은 증가시켰기 때문에 mov edx, so ;다시 첫 번째 주소값을 가리키게 한다.

mov ebx, strlenta ;문자열의 길이를 ebx, ecx레지스터에 각각 대입한다. mov ecx, strlenso

L1:

mov al,[edx] ;soure의 문자를 target문자열 뒤에 대입한다. mov [esi+ebx],al

(37)

loop L1 ret

Str_concat ENDP ;str_concat 프로시져 끝. ;==================================str_concat end

END main

결과 화면 ⋅

Str_remove ○

문자열로부터 n개의 문자를 제거하는 Str_remove 프로시저를 작성하라 문자열 내의 제거될. 문자의 위치를 포인터및 변수로 전달하라 제거하는 문자의 개수를 지정하는 정수를 전달하라. .

소스코드 ⋅

TITLE Str_remove (hello.asm)

INCLUDE \masm615\include\Irvine32.inc

Str_remove PROTO, ;str_remove의 PROTO선언 tar:PTR BYTE,

i:DWORD, j:DWORD

.data

target BYTE "abcxxxxdefghijklmop", 0 ;remove할 문자열

valA DWORD ? ;인자값으로 넘길 2개의 변수선언 valB DWORD ?

prompt1 BYTE "Enter the Number: ",0 ;숫자를 입력받을시 출력할 문자열

.code

;===================================main main PROC

mov edx,OFFSET prompt1 ;2개의 숫자를 입력받는다. call WriteString

(38)

mov valB, eax

INVOKE Str_remove, ADDR target, valA, valB ;입력받는 2개의 숫자를 인자값으로 넘긴다.

exit

main ENDP

;---str Proc

Str_remove PROC, ;target주소값과 2개의 숫자를 파라미터로 설정. tar:PTR BYTE,

i:DWORD, j:DWORD

.data

source BYTE 20 DUP(0) ;복사할 문자열

.code

mov esi,tar ;target의 시작주소를 esi에 대입 mov ecx,SIZEOF source ;source의 문자열값을 ecx에 대입 mov ebx, 0 ;ebx레지스터 0으로 초기화

L1: ;문자열을 복사한다.

mov al,[esi]

mov source[ebx],al inc esi

inc ebx loop L1

mov esi,0 ;esi레지스터값을 0으로 초기화

mov ecx, I ;esi을 값으로 대입한다I .

L2: ;esi제거할 첫문자를 가리킨다.

inc esi loop L2

mov ebx, j ;ebx레지스터 를 대입한다j .

는 몇문자를 제거할 값을 가지고 있다

;ebx .

mov j, SIZEOF source ;반복횟수는 source문자열의 길이에서 값을 제거한I mov eax, j ;만큼 반복한다.

(39)

mov ecx, i

L3: ;제거할 문자의 다음부터 제거를 시작한 곳으로

mov al,source[esi+ebx] ;값을 복사한다. mov source[esi],al

inc esi loop L3

mov edx,OFFSET source ;결과 문자열 출력 call WriteString

ret

Str_remove ENDP END main

결과 화면 ⋅

Str_find ○

문자열에서 문자열의 최초의 출현 위치를 찾아 반환하는 프로시저를 작성

target source Str_find

하라 입력 매개변수는. source문자열에 대한 포인터와 target문자열에 대한 포인터 이어야 한 다 일치가 반결되면 프로시저는 제로 플래그를 설정하고. , EAX를 target문자열에서 일치한 위 치로 설정한다 일치가 발견되지 않으면 제로 플래그는 지워진다. , .

소스코드 ⋅

TITLE Str_find (hello.asm)

INCLUDE \masm615\include\Irvine32.inc

Str_find PROTO, ;str_find PROTO 선언 so : PTR BYTE,

ta : PTR BYTE

.data

target BYTE "123ABC342432", 0 ;섞여 있는 문자열 source BYTE "ABC", 0 ;찾을 문자열

(40)

;===================================main main PROC

mov edx,OFFSET target ;source와 target문자열 출력 call WriteString

call crlf

mov edx,OFFSET source call WriteString

call crlf

INVOKE Str_find, ADDR source, ADDR target ;str_find 프로시저 호출하면서 두문자열의 주소값을

인자값으로 넘겨준다

; .

exit

main ENDP

;---str Proc

Str_find PROC, ;Str_find 프로시저 두 개의 주소값을 파라미터로 받는다. ta : PTR BYTE,

so : PTR BYTE .data

valA DWORD 0 ;첫번째 문자열이 같은 경우 다른문자도 같을때 비교를, 위한 변수

;

pos DWORD 0 ;몇번째에 같은 문자열이 있는지 저장하는 변수

prompt1 BYTE "ABC ", 0 ;결과값 출력시 사용 부터 시작입니다

prompt2 BYTE " . ", 0 prompt3 BYTE "not Found. ", 0

.code

mov esi, so ;soure의 첫 번째 주소값을 esi대입 mov edi, ta ;target의 첫 번째 주소값을 edi대입 mov ebx, valA ;valA를 ebx에 대입

mov eax, 0 ;디버그시 레지스터값을 잘보기 위해 0으로 셋팅 mov edx, 0

L1:

mov al, [esi] ;esi가 가리키고 있는곳의 값을 al에 대입 mov dl, [edi] ;edi가 가리키고 있는곳의 값을 dl에 대입 inc pos ;pos값을 증가

(41)

inc esi ;esi주소값 증가

cmp al, 0 ;al값과 0과 비교해 같으면 제로플레그가 1로 셋팅되기 jnz L1 ;때문에 L4로 이동하고 아니면 계속 반복한다.

jmp L4

L2:

inc esi ;첫문자가 같은 경우 다음문자도 같은지 비교한다. inc edi

mov al, [esi] mov dl, [edi] inc ebx

cmp al, dl ;같으면 다음문자도 비교한다. je L2

cmp ebx, 3 ;3개 문자가 모두 같을 경우 L3로이동 je L3

mov edi, ta ;첫문자 이외에 다를 경우 다시 target주소를 edi에 jmp L1 ;대입후 L1으로 이동

L4:

call DumpRegs ;레지스터값 출력

mov edx,OFFSET prompt3 ;값을 찾을수 없다고 출력후 L5로 이동 call WriteString

jmp L5

L3:

call DumpRegs ;값이 일치할 경우 몇 번째부터 시작인지를 출력한다. mov eax, pos

mov edx,OFFSET prompt1 call WriteString

call WriteDec

mov edx,OFFSET prompt2 call WriteString

L5:

ret ;리턴

(42)

결과 화면 ⋅

어셈블리 언어를 이용한 블록 격파 게임 만들기

8.

소스코드 ○

TITLE GAME

INCLUDE irvine32.inc

width1 = 20 width2 = 18 width3 = 7 width4 = 10 width5 = 4 BufSize = 80

initplay = 345 initdown = -21 initside = 1 initturn = -1 initbarstart = 343 initbarwidth = 4 initspeed = 80

.data

buffer BYTE BufSize DUP(?),0,0 stdInHandle DWORD ?

bytesRead DWORD ?

gamestart BYTE width1 DUP(2ah),0ah

BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE "* GAME START *", 0ah

(43)

BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE width1 DUP(2ah),0

gamefinish BYTE width1 DUP(2ah),0ah

BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE "* GAME FINISH *", 0ah BYTE "* GAME FINISH *", 0ah BYTE "* GAME FINISH *", 0ah BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE 2ah, width2 DUP(20h), 2ah, 0ah BYTE width1 DUP(2ah),0

string1 BYTE 441 DUP(4DH), 0

stage1 BYTE width1 DUP(2ah),0ah

(44)

BYTE 2ah, width5 DUP(20h), width4 DUP(4Dh), width5 DUP(20h), 2ah, 0ah 3 BYTE 2ah, width5 DUP(20h), width4 DUP(4Dh), width5 DUP(20h), 2ah, 0ah 4 BYTE 2ah, width5 DUP(20h), width4 DUP(4Dh), width5 DUP(20h), 2ah, 0ah 5 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 6

BYTE 2ah, width2 DUP(20h), 2ah, 0ah 7 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 8 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 9 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 10 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 11 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 12 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 13 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 14 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 15

BYTE 2ah, width3 DUP(20h), 4 DUP(2ah), width3 DUP(20h), 2ah, 0ah 16 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 17

BYTE 2ah, width2 DUP(20h), 2ah, 0ah 18 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 19 BYTE width1 DUP(44h), 0 20

BYTE width1 DUP(2ah),0ah

BYTE 2ah, width2 DUP(20h), 2ah, 0ah 1 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 2

BYTE 2ah, 3 DUP(20h), 3 DUP(4Dh), 1 DUP(20h), 4 DUP(4Dh), 1 DUP(20h), 3 DUP(4Dh), 3 DUP(20h), 2ah, 0ah 3

BYTE 2ah, 3 DUP(20h), 3 DUP(4Dh), 1 DUP(20h), 4 DUP(4Dh), 1 DUP(20h), 3 DUP(4Dh), 3 DUP(20h), 2ah, 0ah 4

BYTE 2ah, 3 DUP(20h), 3 DUP(4Dh), 1 DUP(20h), 4 DUP(4Dh), 1 DUP(20h), 3 DUP(4Dh), 3 DUP(20h), 2ah, 0ah 5

BYTE 2ah, width2 DUP(20h), 2ah, 0ah 6 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 7 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 8 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 9 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 10 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 11 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 12 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 13 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 14 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 15

BYTE 2ah, width3 DUP(20h), 4 DUP(2ah), width3 DUP(20h), 2ah, 0ah 16 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 17

(45)

BYTE width1 DUP(44h), 0 20

BYTE width1 DUP(2ah),0ah

BYTE 2ah, width2 DUP(20h), 2ah, 0ah 1 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 2

BYTE 2ah, 2 DUP(20h), 4 DUP(4Dh), 2 DUP(20h), 3 DUP(4Dh), 2 DUP(20h), 3 DUP(4Dh), 2 DUP(20h), 2ah, 0ah 3

BYTE 2ah, 3 DUP(20h), 3 DUP(4Dh), 1 DUP(20h), 4 DUP(4Dh), 1 DUP(20h), 3 DUP(4Dh), 3 DUP(20h), 2ah, 0ah 4

BYTE 2ah, 2 DUP(20h), 4 DUP(4Dh), 2 DUP(20h), 3 DUP(4Dh), 2 DUP(20h), 3 DUP(4Dh), 2 DUP(20h), 2ah, 0ah 5

BYTE 2ah, width2 DUP(20h), 2ah, 0ah 6 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 7 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 8 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 9 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 10 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 11 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 12 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 13 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 14 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 15

BYTE 2ah, width3 DUP(20h), 4 DUP(2ah), width3 DUP(20h), 2ah, 0ah 16 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 17

BYTE 2ah, width2 DUP(20h), 2ah, 0ah 18 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 19 BYTE width1 DUP(44h), 0 20

BYTE width1 DUP(2ah),0ah

BYTE 2ah, width2 DUP(20h), 2ah, 0ah 1 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 2

BYTE 2ah, width5 DUP(20h), width4 DUP(4Dh), width5 DUP(20h), 2ah, 0ah 3 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 4

BYTE 2ah, width5 DUP(20h), width4 DUP(4Dh), width5 DUP(20h), 2ah, 0ah 5 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 6

BYTE 2ah, width5 DUP(20h), width4 DUP(4Dh), width5 DUP(20h), 2ah, 0ah 7 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 8

(46)

BYTE 2ah, width2 DUP(20h), 2ah, 0ah 15

BYTE 2ah, width3 DUP(20h), 4 DUP(2ah), width3 DUP(20h), 2ah, 0ah 16 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 17

BYTE 2ah, width2 DUP(20h), 2ah, 0ah 18 BYTE 2ah, width2 DUP(20h), 2ah, 0ah 19 BYTE width1 DUP(44h), 0 20

stringScore BYTE " SCORE : ", 0 Score DWORD 300

stringLevel BYTE " LEVEL : ", 0 Level DWORD 2

finish DWORD 1

Ball BYTE 4fh block BYTE 2ah clearblock BYTE 20h

play SDWORD initplay down SDWORD initdown side SDWORD initside turn SDWORD initturn

barstart SDWORD initbarstart barwidth SDWORD initbarwidth speed SDWORD initspeed

.code main PROC

mov ecx, 10 L11:

call Clrscr mov eax, speed

mov edx, OFFSET gamestart call writestring

(47)

mov eax, 15 call setTextColor

mov eax, 0 mov ecx, 0 mov edx, 0 mov bl, Ball mov bh, clearblock

call copystage

L1:

mov eax, speed call Delay call Clrscr

call checkup call checkside call checkupside

INVOKE GetStdHandle, STD_INPUT_HANDLE mov stdInHandle,eax

INVOKE PeekConsoleInput, stdInHandle, ADDR buffer, BufSize - 2, ADDR bytesRead

INVOKE FlushConsoleInputBuffer, stdInHandle

mov esi, OFFSET buffer add esi, 10

mov cl, [esi] cmp cl, 37 jne L2 mov cl, 0 mov [esi], cl call moveleft L2:

(48)

mov [esi], cl call moveright

L3:

mov esi, OFFSET string1 add esi, play

add esi, down add esi, side

mov [esi], bl

mov edx, OFFSET string1

call writestring call crlf

mov eax, 0 mov eax, play add eax, down add eax, side mov play, eax mov cl, [esi] cmp cl, Ball jne L4

mov [esi], bh L4:

mov edx, 0

mov edx, OFFSET stringScore call writestring

mov eax, Score call writedec call crlf

call checkscore

mov edx, 0

mov edx, OFFSET stringLevel call writestring

mov eax, Level call writedec

(49)

cmp ecx, 1 je L1

mov ecx, 10 L22:

call Clrscr

mov edx, OFFSET gamefinish call writestring

call crlf

mov edx, OFFSET stringScore call writestring

mov eax, Score call writedec call crlf

mov edx, OFFSET stringLevel call writestring

mov eax, Level call writedec

mov eax, speed call delay mov ebx, ecx add ebx, 1 mov eax, ebx call SetTextColor loop L22

mov eax, 15 call setTextColor

exit main ENDP

checkup PROC pushad

mov esi, OFFSET string1 add esi, play

add esi, down

(50)

jne L2

mov eax, down imul turn mov down, eax

L2:

cmp al, 4Dh jne L3

mov eax, down imul turn mov down, eax

mov bl, clearblock mov [esi], bl

mov ecx, Score add ecx, 10 mov Score, ecx

L3:

cmp al, 44h jne L4 mov eax, 0 mov finish, eax L4:

popad ret checkup ENDP

checkside PROC pushad

mov esi, OFFSET string1 add esi, play

add esi, side

mov al, [esi] cmp al, 2ah jne L2

(51)

imul turn mov side, eax

L2:

cmp al, 4Dh jne L3

mov eax, side imul turn mov side, eax

mov bl, clearblock mov [esi], bl

mov ecx, Score add ecx, 10 mov Score, ecx

L3:

popad ret checkside ENDP

checkupside PROC pushad

mov esi, OFFSET string1 add esi, play

add esi, down add esi, side

mov al, [esi] cmp al, 2ah jne L2

mov eax, down imul turn mov down, eax

(52)

L2:

cmp al, 4Dh jne L3

mov eax, down imul turn mov down, eax

mov eax, side imul turn mov side, eax

mov bl, clearblock mov [esi], bl

mov ecx, Score add ecx, 10 mov Score, ecx

L3:

popad ret checkupside ENDP

moveright PROC pushad

mov bl, block mov bh, clearblock

mov esi, OFFSET string1 add esi, barstart add esi, barwidth add esi, 1

mov al, [esi] cmp al, 2ah je L2

cmp al, Ball je L2

mov eax, barstart add eax, 1

(53)

mov [esi], bl sub esi, barwidth mov [esi], bh L2:

popad ret moveright ENDP

moveleft PROC pushad

mov bl, block mov bh, clearblock

mov esi, OFFSET string1 add esi, barstart mov al, [esi] cmp al, 2ah je L2

cmp al, Ball je L2

mov eax, barstart sub eax, 1

mov barstart, eax

mov [esi], bl add esi, barwidth mov [esi], bh L2:

popad ret moveleft ENDP

copystage PROC pushad

mov esi, OFFSET string1 mov edi, OFFSET stage1 mov eax, Level

(54)

L1:

mov eax, 0 mov al, [edi] mov [esi], al inc esi inc edi cmp al, 0 jne L1

mov speed, initspeed mov play, initplay mov down, initdown mov side, initside mov turn, initturn

mov barstart, initbarstart mov barwidth, initbarwidth mov speed, initspeed popad

ret copystage ENDP

checkscore PROC pushad

mov eax, Level dec eax

mov ecx, 300 mul ecx mov ebx, eax mov eax, Score sub eax, ebx cmp eax, 300

jne L1

mov eax, Score cdq

mov ebx, 300 idiv ebx cmp edx, 0 jne L1

mov eax, Level inc eax

(55)

cmp eax, 5

mov edx, 0 mov finish, edx je L1

mov edx, 1 mov finish, edx call copystage L1:

popad ret checkscore ENDP

END main

결과 화면 ○

초기 화면 < >

게임 화면 종료 화면

(56)

9. References

어셈블리언어

References

Related documents

When guests or service people arrive and the access gate is closed, they can look up your name on the directory at the keypad located conveniently outside the entry gate. Next to

placed in receivership, involuntary liquidation or under administration?. Yes No If ‘Yes’, please provide full details including when this occured. If you have a second

2007-present Judge Pro Tempore- King County District Court; Seattle Municipal Court?. 2008 Judge Pro Tempore- Lake Forest Park

This document provides information about the supported hardware and software versions for the Dell PowerVault™ Backup to Disk Appliance system.. NOTE: The versions specified in

The evaluation will use Non Equivalent Control Group Quasi Experimental Design because randomization of research areas to intervention and control groups will not be possible

16 Updated September 17, 2012   Answer options A and B bring additional debt exposure to the client. Additional debt exposure for a client heavily indebted will jeopardize

Time is tall but worksheets pdf worksheet shows a compound sentences with sentences using coordinating, subordinating conjunctions indicated to bring together.. All of conjunctions

The establishment of historic district overlay zoning and the creation of local historic districts and design review boards has developed in response to the failures of