티스토리 뷰
[전광성의 어셈블리어 이해하기:4회] 프로그래밍에 필요한 명령어와 디렉티브 (2)
산술 연산에 영향을 받는 플래그
산술 연산을 하다 보면 최대값을 뛰어넘어 오버플로우가 발생하기도 한다. 이럴 때 어떻게 처리를 해주어야 할까? 플래그(Flags)를 이용하면 된다. 플래그는 산술연산을 수행한 후, 어떤 상태가 되었는지에 대해 알려준다. 단지 오버플로우 뿐만 아니라 계산 후 0이 되었는지, 부호가 붙었는지 등을 표시해 준다.
조심해야 할 것은 산술 연산을 두 번 수행하면 가장 최근의 상태만이 플래그에 남아있다는 것이다. 또한 특정 명령을 수행 한 후 플래그가 어떻게 변해 있을지 정의되지 않은 명령도 있으니 조심하기 바란다. 각 플래그는 1bit씩을 차지하며, 이러한 플래그를 모아놓은 것이 EFLAGS 레지스터이다. 이는 레지스터 메모리를 설명할때 이미 설명했었다.
OFFSET 연산자
< 그림 1 : OFFSET >
OFFSET연산자는 데이터 레이블의 오프셋을 알아낼 때 사용된다. 오프셋은 특정 기준 위치로부터 떨어진 거리를 뜻하며, 특히 여기서는 데이터 세그먼트로부터의 거리를 이야기 한다. 그림1을 참고하면 좀 더 이해가 빠를 것이다. 포인터를 사용하려면 이 OFFSET연산자를 이용해서 데이터 세그먼트로부터의 거리를 알아내어야 한다. 구체적인 사용 예는 후에 인다이렉트 오퍼랜드(Indirect Operands)를 설명할 때 하겠다.
PTR 연산자
PTR연산자는 피연산자의 사이즈(8bit/16bit/32bit)대신 임의의 사이즈로 읽어올 수 있다. 직접적으로 대응되는 것은 아니지만, 일종의 형 변환이라고 생각해도 무방하다. 예를 들어 보이겠다.
하지만 예전에 배운 리틀 엔디안 오더를 잊지 않았길 바란다. 12345678h에서 최하위 바이트는 78이다. 하위바이트부터 하위 주소의 메모리에 적재되므로 78 56 34 12이렇게 적재된다.(78쪽이 하위 주소의 메모리이고 12쪽이 상위 주소의 메모리이다)
TYPE 연산자
TYPE 연산자는 사이즈를 바이트 단위로 리턴해 준다. TYPE의 뒤에는 변수명이 와야한다. 다음과 같이 데이터가 정의되어 있다고 하자. TYPE 연산자를 사용하면, 표1과 같은 값을 갖게 될 것이다.
< 표 1 : TYPE 연산자 >
인다이렉트 오퍼랜드(Indirect Operands)
아까 설명한 OFFSET연산자로 오프셋을 레지스터 변수에 저장시킨 후 그 변수를 포인터로 사용할 수 있다. 다음의 예를 보자.
이렇게 var1의 오프셋을 esi에 저장시킨 후 [esi]를 이용하여 간접적으로 var1을 사용할 수 있다.
배열
이제 배열을 사용하는 방법을 설명해 주겠다. 앞에 나왔던 것이므로 이해하기 어렵지 않을 것이다.
[array + 2] 이렇게 한 것은 배열이 WORD형이기 때문이다. C에서 int ary[3]; 라고 했을 때 *(ary + 1)이렇게만 사용해도 두번째 원소에 접근할 수 있었던 것과 다르다는 것을 느낄 것이다. 어셈블리어에서는 주소 연산의 더하기는 데이터 형에 상관없이 항상 바이트 단위로 된다는 것을 잊지 않길 바란다.
아래와 같은 방법으로도 배열을 사용할 수 있다.
이전에 배운 인다이렉트 오퍼랜드(Indirect Operands)를 사용하였다. 조심할 것은 esi를 증가시킬 때 원소 하나의 크기 (여기서는 WORD이므로 2)만큼 증가시켜줘야 한다는 것이다.
저자: 전광성 | 날짜: 2005년 02월 04일 |
1 .0 여러가지 명령어(MOV, 다이렉트-오프셋 오퍼랜드, ADD, SUB) |
0 플래그와 연산자(OFFSET, PTR, TYPE, 인다이렉트 오퍼랜드) 및 배열 |
3 .0 JMP, LOOP 명령과 예제 |
산술 연산을 하다 보면 최대값을 뛰어넘어 오버플로우가 발생하기도 한다. 이럴 때 어떻게 처리를 해주어야 할까? 플래그(Flags)를 이용하면 된다. 플래그는 산술연산을 수행한 후, 어떤 상태가 되었는지에 대해 알려준다. 단지 오버플로우 뿐만 아니라 계산 후 0이 되었는지, 부호가 붙었는지 등을 표시해 준다.
조심해야 할 것은 산술 연산을 두 번 수행하면 가장 최근의 상태만이 플래그에 남아있다는 것이다. 또한 특정 명령을 수행 한 후 플래그가 어떻게 변해 있을지 정의되지 않은 명령도 있으니 조심하기 바란다. 각 플래그는 1bit씩을 차지하며, 이러한 플래그를 모아놓은 것이 EFLAGS 레지스터이다. 이는 레지스터 메모리를 설명할때 이미 설명했었다.
- - 제로 및 사인 플래그(Zero and Sign Flags)
- - 캐리 플래그(Carry Flag)
- - 오버플로우 플래그(Overflow Flag)
OFFSET연산자는 데이터 레이블의 오프셋을 알아낼 때 사용된다. 오프셋은 특정 기준 위치로부터 떨어진 거리를 뜻하며, 특히 여기서는 데이터 세그먼트로부터의 거리를 이야기 한다. 그림1을 참고하면 좀 더 이해가 빠를 것이다. 포인터를 사용하려면 이 OFFSET연산자를 이용해서 데이터 세그먼트로부터의 거리를 알아내어야 한다. 구체적인 사용 예는 후에 인다이렉트 오퍼랜드(Indirect Operands)를 설명할 때 하겠다.
PTR연산자는 피연산자의 사이즈(8bit/16bit/32bit)대신 임의의 사이즈로 읽어올 수 있다. 직접적으로 대응되는 것은 아니지만, 일종의 형 변환이라고 생각해도 무방하다. 예를 들어 보이겠다.
- .data
myDouble DWORD 12345678h
.code
mov ax, WORD PTR myDouble ; ax 는 5678h
하지만 예전에 배운 리틀 엔디안 오더를 잊지 않았길 바란다. 12345678h에서 최하위 바이트는 78이다. 하위바이트부터 하위 주소의 메모리에 적재되므로 78 56 34 12이렇게 적재된다.(78쪽이 하위 주소의 메모리이고 12쪽이 상위 주소의 메모리이다)
TYPE 연산자는 사이즈를 바이트 단위로 리턴해 준다. TYPE의 뒤에는 변수명이 와야한다. 다음과 같이 데이터가 정의되어 있다고 하자. TYPE 연산자를 사용하면, 표1과 같은 값을 갖게 될 것이다.
- var1 BYTE ? ; 초기화 하지 않는다는 표시
var2 WORD ?
var3 DWORD ?
var4 QWORD ?
수식 | 값 |
Type var1 | 1 |
Type var 2 | 2 |
Type var 3 | 4 |
Type var 4 | 8 |
아까 설명한 OFFSET연산자로 오프셋을 레지스터 변수에 저장시킨 후 그 변수를 포인터로 사용할 수 있다. 다음의 예를 보자.
- .data
var1 BYTE 10h
.code
mov esi, OFFSET var1
mov al, [esi] ; AL = 10h
mov [esi], 0 ; var1 = 0
이렇게 var1의 오프셋을 esi에 저장시킨 후 [esi]를 이용하여 간접적으로 var1을 사용할 수 있다.
이제 배열을 사용하는 방법을 설명해 주겠다. 앞에 나왔던 것이므로 이해하기 어렵지 않을 것이다.
- .data
array WORD 1000h, 2000h, 3000h ; 워드형 원소가 세개인 배열
.code
mov ax, array ; ax = 1000h
mov ax, [array + 2] ; ax = 2000h
mov ax, [array + 4] ; ax = 3000h
[array + 2] 이렇게 한 것은 배열이 WORD형이기 때문이다. C에서 int ary[3]; 라고 했을 때 *(ary + 1)이렇게만 사용해도 두번째 원소에 접근할 수 있었던 것과 다르다는 것을 느낄 것이다. 어셈블리어에서는 주소 연산의 더하기는 데이터 형에 상관없이 항상 바이트 단위로 된다는 것을 잊지 않길 바란다.
아래와 같은 방법으로도 배열을 사용할 수 있다.
- .data
array WORD 1000h, 2000h, 3000h ; 워드형 원소가 세개인 배열
.code
mov esi, OFFSET array
mov ax, [esi] ; ax = 1000h
add esi, 2
mov ax, [esi] ; ax = 2000h
add esi, 2
mov ax, [esi] ; ax = 3000h
이전에 배운 인다이렉트 오퍼랜드(Indirect Operands)를 사용하였다. 조심할 것은 esi를 증가시킬 때 원소 하나의 크기 (여기서는 WORD이므로 2)만큼 증가시켜줘야 한다는 것이다.
'기억하자정보 > 자바스크립트' 카테고리의 다른 글
[전광성의 어셈블리어 이해하기:5회] 프로시져(Procedure) (1) (0) | 2006.09.06 |
---|---|
[전광성의 어셈블리어 이해하기:4회] 프로그래밍에 필요한 명령어와 디렉티브 (3) (0) | 2006.09.06 |
[전광성의 어셈블리어 이해하기:4회] 프로그래밍에 필요한 명령어와 디렉티브 (1) (0) | 2006.09.06 |
[전광성의 어셈블리어 이해하기:3회] 어셈블리언어 기초 (3) (0) | 2006.09.06 |
[전광성의 어셈블리어 이해하기:3회] 어셈블리언어 기초 (2) (0) | 2006.09.06 |
- 안내
- 궁금한 점을 댓글로 남겨주시면 답변해 드립니다.