/* 
written by kaspy (kaspyx@gmail.com)
*/ 

문득 어셈블리 언어를 보다보면 자주쓰지 않는 만큼 해깔릴수 있는것들이 많은것 같아서 정리해보았다. 특히 주소 연산 mov [100], 10 같은것들
많이 사용되지 않는 16bit 어셈블리어지만 레지스터 크기나 명령어 이름만 조금 바꾼 형태로 익힌다면 32bit도 그리 어렵지는 않을것이다.

이번에는 비교 및 분기문, 특수연산 등으로 정리하였다.

JG 및 JA 명령어

예제)

  1. mov bl, 5
  2. cmp al, bl
  3. jg 0188
  4. ja 018a
  5.  
  6. ;bl 레지스터에 5를 저장하고 al과 비교하여 클 경우 018a 주소로 번지시킵니다.
  7. ;여기서 jg 구문에서 점프하지 않고 ja에서 한 이유는 jg는 부호있는 검사를 하여 al의 값은 음수가 됩니다.
  8. ;이때는 al이 bl 보다 작으며 ja 로 비교했을 경우는 부호없는 비교이기 때문에
  9. ;al은 ff로 비교하게되고 참이기 때문에 018a 번지로 점프합니다.


JL 명령어

예제)

  1. cmp al, bl
  2. jl 198
  3.  
  4. ;al과 bl을 비교하여 al이 작을 경우 198번지로 이동합니다.
  5. ;jl 은 부호있는 음수로 비교하기 때문에 al레지스터는 ff가 아니라 -7f입니다.
  6. ;bl = 5 이기 때문에 작다는 조건을 만족하고 198번지로 이동합니다.


JL JA JG 명령어

예제)

  1. cmp al, bl
  2. jl 01aa
  3. ja 01ac
  4. jg 01ae
  5.  
  6. ;al과 bl을 비교해서 참값이 되면 해당번지로 점프시킵니다.
  7. ;여기서 jl 은 부호있는 비교이기 때문에 bl은 ff가 아니라 -7f이고 al은 5이기 때문에 조건을 만족하지 않습니다.
  8. ;ja는 부호없는 비교이며 이때는 bl이 ff이므로 조건을 만족하지 않아 점프하지 않고
  9. ;jg는 부호있는 비교이므로 al은 5 그리고 bl은 -7f 와 비교하여 al이 더크기 때문에 1ae번지로 점프합니다.


LOOP 명령어

예제)

  1. mov cx, 8
  2. inc ax
  3. loop 01b6
  4.  
  5. ;cx레지스터가 0이 될 때까지 감소 시키면서 (loop)01b6 번지를 반복합니다.
  6. ;01b6번지는 inc ax이며 8번 반복하여 ax가 8이 되었습니다.


SHR 명령어

예제)

  1. shr bh, 1
  2.  
  3. ;bh 레지스터를 오른쪽으로 1만큼 쉬프트 연산합니다.


AND, NOT, OR, XOR 명령어

예제)

  1. and al, bl
  2. not al
  3. or al, bl
  4. xor al, bl
  5.  
  6. ;해당 레지스터와 al <- al 연산 bl
  7. ;논리연산 and, not, or, xor를 수행합니다.
  8. ;not은 1이면 0으로 0은 1로 바꿉니다.


LODSB 명령어

예제)

  1. lodsb
  2.  
  3. ;ax의 하위 1바이트 al 레지스터에 ds 세그먼트 오프셋 si 의 값을 저장합니다. 즉
  4. ;al <- ds:si

REPZ, STOSW 명령어

예제)

  1. mov cx, 07d0
  2. repz
  3. stosw
  4.  
  5. ;cx에 07d0를 저장하고 repz 와 stosw를 실행하면 cx레지스터를 0이 될 때까지 1씩 감소시키며
  6. ;반대로 di는 2byte(1word) 증가시키며 ax의 값을 es:di 의 주소값에에 복사를 합니다.
  7. ;es의 b800 주소값은 Video ram이 시작되는 부분으로 여기의 값을 수정하면 화면을 제어할수 있습니다.
  8. ;es:0000부터 es:0fa0 까지 20과 07을 저장합니다.


명령어 응용

예제)

  1. lea si, arr1
  2. mov di, 160*10 + 2*30
  3. lp: lodsb
  4.    mov ah, 7
  5.    stosw
  6.    loop lp
  7.  
  8. ;arr1은 "hello" 라는 문자열이 저장되어있는 있음
  9. ;si에 arr1배열의 시작주소를 si에 넣고 160 *10 + 2*30 (화면의 정중앙)의 값을 di에 저장합니다.
  10. ;lodsb를 하면 ds:si 의 값을 al에 1byte 저장하고 ah에는 7을 저장합니다. 그리고
  11. ;stosw를 하면 문자열 hello문자열을 차례대로 가져와서 stosw를 통해 화면의 정중앙에 문자열을 출력해줍니다.
  12. ;이상하게 es:di 의 값이 stosw을 통해 의도적으로 바뀌지 않았는데 이는 화면이 수시로 바뀌는 특성 때문에 그런거 같습니다.
  13. ;또한 메모리 시작주소 b800h 영역은 프롬프트상에서 비디오 출력 메모리 공간임을 추측할수 있었습니다.

추가**

  1. mov ah, 9
  2. int 21h
  3. ; 이명령을 추가로 실행시켜주면 아래와 같은 문자열이 출력됨


* 관련 링크 참조

http://kaspyx.tistory.com/entry/16bit-Assembly-예제-정리-1

http://kaspyx.tistory.com/entry/16bit-Assembly-예제-정리-2

http://kaspyx.tistory.com/entry/16bit-Assembly-예제-정리-3

신고
Posted by 캐스피
/* 
written by kaspy (kaspyx@gmail.com)
*/ 


문득 어셈블리 언어를 보다보면 자주쓰지 않는 만큼 해깔릴수 있는것들이 많은것 같아서 정리해보았다. 특히 주소 연산 mov [100], 10 같은것들
많이 사용되지 않는 16bit 어셈블리어지만 레지스터 크기나 명령어 이름만 조금 바꾼 형태로 익힌다면 32bit도 그리 어렵지는 않을것이다.
(ex. 16bit 레지스터 ax -> 32bit는 eax)

이어서 진행~


문자열 출력

예제)

  1. mov ah, 9
  2. int 21h
  3.  
  4. ;ax의 상위 레지스터 ax에 9를 저장하고 int 21h명령어를 실행시키면 dx에 주소에 저장된 값의 문자가 
  5. ;'$' 가 나올 때 까지 출력됩니다.


ES 세그먼트 오프셋을 이용한 MOV

예제)

  1. mov es, ax
  2. mov ax, [0000]
  3. ; mov ax, es[0]
  4.  
  5. ; ax에 있는 ffff의 값을 es 레지스터에 저장합니다. 
  6. ; 그리고 mov ax, es[0] 명령어를 수행하는데 es에는 ffff 가 들어가있습니다.
  7. ; mov ax, es[0] 를 하면 실제 주소는 es의 주소값 ffff:0000 이 실제 값입니다. 
  8. ; ffff:0000 에 저장되어있는 값을 ax에 저장합니다.


POP 명령어

예제)

  1. pop ax
  2. ; ax 레지스터에 현재 스택포인터(sp) 값을 저장합니다.


RET 명령어

예제)

  1. ret
  2.  
  3. ;ret 명령어는 sp가 가리키는 값을 ip 에 넣어주고 sp를 증가 시킵니다.


SUB 명령어

예제)

  1. mov ax, 0000
  2. sub ax, 0001
  3.  
  4. ; ax에 0을 넣어주고 1을 빼줍니다.
  5. ; 그러면 ax는 실제로 1111 1111 1111 1111 이며 맨 앞에 비트가 1이므로 ng
  6. ; 그리고 짝수이므로 pe 그리고 내림수가 나왔기 때문에 cy 로 플래그가 켜졌습니다.



ADC, SBB 명령어

예제)

  1. mov bx, 2
  2. adc ax, bx  
  3. sbb ax, bx
  4.  
  5. ;ax = 0xffff
  6. ;bx에 2를 저장하고 ax에 bx를 더합니다.
  7. ;ax는 한계치를 넘었고 carry bit가 있기 때문에 ffff + 2는 2가 됩니다. 마찬가지로
  8. ;sbb ax, bx 는 버림수와 같이 계산하고 ffff가 됩니다.


MUL 명령어

예제)

  1. mov ax, 2003
  2. mov cx, 11
  3. mul cx
  4.  
  5. ;ax 레지스터에 2003을 넣고 cx 레지스터에는 11을 넣은다음에 mul cx를 하면
  6. ;ax = ax * cx 값이 들어가게 됩니다.
  7. ;그런데 ax가 표현할수 있는 한계치를 초과하여 오버 플로우 플래그 nv에서 ov로 바뀌었습니다.


IMUL 명령어

예제)

  1. mov ax, ffff
  2. mov cx, 5
  3. imul cx
  4.  
  5. ;ax에 16진수 ffff를 저장하고 cx에 5를 저장해서
  6. ;부호있는 정수형 곱셈 ax <- ax * cx를 해줍니다.
  7. ;이때 ax는 음수이며 맨앞의 1비트를 제외하고 5를 곱하기 때문에
  8. ;ovflow와 carryflag는 켜지지 않습니다.


DIV 명령어

예제)

  1. mov cl, 11
  2. div cl
  3.  
  4. ;ax에서 cl로 나누어 주고 ah에는 몫을 al에는 나머지를 저장합니다.

* 관련 링크 참조

http://kaspyx.tistory.com/entry/16bit-Assembly-예제-정리-1

http://kaspyx.tistory.com/entry/16bit-Assembly-예제-정리-3

http://kaspyx.tistory.com/entry/16bit-Assembly-예제-정리-4

신고
Posted by 캐스피
/* 
written by kaspy (kaspyx@gmail.com)
*/ 


문득 어셈블리 언어를 보다보면 자주쓰지 않는 만큼 해깔릴수 있는것들이 많은것 같아서 정리해보았다. 특히 주소 연산 mov [100], 10 같은것들
많이 사용되지 않는 16bit 어셈블리어지만 레지스터 크기나 명령어 이름만 조금 바꾼 형태로 익힌다면 32bit도 그리 어렵지는 않을것이다.
(ex. 16bit 레지스터 ax -> 32bit는 eax)

우선은 간단한 명령어부터~

MOV 레지스터, 숫자

예제)

  1. ; ax 레지스터에 지정된 숫자를 넣어줍니다.
  2. mov ax, 3


MOV 레지스터, [주소]

예제)

  1. mov ax, [0103]
  2. ;mov ax, x(변수)
  3.  
  4. ;ax 레지스터에 지정된 숫자를 넣어줍니다. 
  5. ;여기서는 0103 번지의 값을 ax에 넣으라는 소린데 이는 소스코드에서 x의 주소입니다.


MOV [주소], 숫자

예제)

  1. mov word ptr [0103]2013
  2.  
  3. ;0103 주소에 저장되어 있는 값에 word 만큼의 크기로 2013 이라는 값을 저장합니다.
  4. ;(20 상위 주소에 13은 하위 주소에)


MOV 레지스터, 숫자+배열 인덱스

예제)

  1. mov dl, [bx+0105]
  2. ; mov dl, y[bx]
  3.  
  4. ; bx레지스터의 값 + 105 주소의 값을 dx레지스터 하위 1바이트 레지스터에 저장합니다.
  5. ; 이와 같이 bx레지스터는 인덱스에 사용됩니다.



MOV 레지스터, 레지스터

예제)

  1. mov ds, ax
  2.  
  3. ;데이터 세그먼트(ds)나 엑스트라 세그먼트(ex)도 값을 바꿀 수 있습니다.


INC [주소]

예제)

  1. inc byte ptr [bx]
  2.  
  3. ;bx에 저장된 값의 주소의 값을 1 증가시킵니다. (모르는 주소)


* 관련 링크 참조

http://kaspyx.tistory.com/entry/16bit-Assembly-예제-정리-2

http://kaspyx.tistory.com/entry/16bit-Assembly-예제-정리-3

http://kaspyx.tistory.com/entry/16bit-Assembly-예제-정리-4

신고
Posted by 캐스피


티스토리 툴바