'movzx'에 해당되는 글 1건

  1. 2009.05.11 [어셈블리어] 데이터 전송 명령어 mov, movzx, movsx
2009. 5. 11. 16:10

[어셈블리어] 데이터 전송 명령어 mov, movzx, movsx

MOV 명령

소스 피연산자로부터 도착점 피연산자로 데이터를 이동시킨다.

데이터 전송 명령으로 알려진 이 명령은 실질적으로 모든 프로그램에서 사용된다.

이 명령의 기본 포멧은 첫 번째 피연산자가 도착점이고 두 번째 피연산자가 소스이다.

MOV destination,source

오른쪽에서 왼쪽으로의 데이터 이동은 C++ 이나 자바에서의 할당 문과 유사하다

dest=source;

[거의 모든 어셈블리 언어 명령에서,

왼쪽 피연산자는 도착점이고,

오른쪽 피연산자는 소스이다.]

MOV는 피연산자의 사용에 있어서 다음의 규칙만을 따르면 된다.

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

2. 피연산자는 모두 메모리 피연산자일 수 없다.

3. CS, EIP, IP는 도착점 피연산자가 될 수 없다.

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

 

세그먼트 레지스터는 프로그램이 실제 주소 모드로 동작될 때만 사용할 수 있다.

CS가 도착점 피연산자로 사용될 수 없다는 것을 제외하고 다음과 같은 옵션이 가능하다.

MOV r/m16, sreg

MOV sreg,r/m16

 

메모리에서 메모리로 MOV 명령은 하나의 메모리 위치에서 다른 위치로 데이터를 이동시키는 데 사용할 수 없다.

대신에 도착점 피연산자로 이동하기 전에 소스 피연산자를 레지스터로 이동시킬 수 있다.

.data

var1 WORD ?

var2 WORD ?

.code

mov ax,var1

mov var2,ax

 

변수나 레지스터로 이동될 때 정수 상수가 몇 바이트가 필요한지를 먼저 고려해야만 한다.

 

작은 피연산자에서 큰 피연산자로 정수를 복사하기 위하여 MOV 명령을 사용하는 것은 오류를 발생시킨다.

그러나 때때로 그렇게 할 필요성이 있을 때가 있다.

count(부호가 없는 16비트)를 ECX(32비트)로 옮겨야 한다고 가정하자. 간단한 해결방법은 ECX를 0으로 지정하고 난 후 count를 CX로

옮기는 것이다.

.date

count WORD 1

.code

MOV ecx, 0

MOV cx, count

 

만약 부호가 있는 정수 -16을 같은 방법으로 시도한다면 어떤일이 일어나는가?

.data

signedVal SWORD -16                          ; FFF0h(-16)

.code

MOV ecx, 0

MOV cx, signedVal                              ; ECX = 0000FFF0h (+65520)

 

ECX(+65520)값은 -16 과 완전히 다른 값이다. 반면에, ECX를 FFFFFFFFh로 채운 후 signedVal을 CX에 복사한다면 마지막 값은 올바를 것이다.

 

MOV ecx, 0FFFFFFFFh                         //0FFFFFFFFh

MOV cx, sigendVal                              ; ECX=FFFFFFF0h

 

이것은 부호가 있는 정수를 다룰 때 문제를 야기한다. 도착점 피연산자를 어떻게 채울지 결정하기 위하여 그 수가 양수인지 음수인지를 점검해야 하는 것은 불편하다. 다행스럽게도 인텔 공학자들은 인텔 386 프로세서를 설계할 때 이 문제를 고려하였고 부호가 없는 정수와 부호가 있는 정수를 다루기 위한 명령어로 <OVZX와 MOVSX 명령어를 도입하였다.

예제)  aaa.asm 파일

TITLE move
INCLUDE Irvine32.inc
.data
             signedVal SWORD -16
.code
main PROC
             mov ecx,0FFFFFFFFh
             mov cx,signedVal
             call DumpRegs
             exit
main ENDP
END main

 

MOVZX 명령 (부호가 없는)

소스 피연산자를 도착점 피연산자로 복사하고 그 값을 16비트나 32비트로 확장한다. 이 명령은 부호가 없는 정수에만 사용된다.

3개의 변형이 가능하다.

 

MOVZX      r32, r/m8                                    //[32비트 범용 레지스터], [8비트 피연산자,8비트 범용레지스터나 메모리 바이트]

MOVZX      r32,r/m16

MOVZX      r16,r/m8

 

첫 번째 피연산자는 도착점이고 두 번째가 소스이다. 도착점은 레지스터여야만 한다.

다음 그림은 8비트 소스 피연산자가 제로 확장되어 16비트 도착점으로 이동하는 모습을 보여 준다.

 

 


다음 예는 피연산자가 모두 레지스터일 때 크기의 변형을 보여 준다.

MOV bx,0A69Bh

MOVZX EAX, BX                                     ; EAX = 0000A69Bh          //16비트 BX의 값이 이동

MOVZX EDX, BL                                     ; EDX = 0000009Bh           //8비트 BL(BX의 하위 8비트)값이 이동

MOVZX CX, BL                                       ; CX = 009Bh                   //8비트 BL값이 이동

 

다음의 에는 소스를 메모리 피연산자를 사용한 경우로서 같은 결과를 만든다.

 

.data

byte1 BYTE 9Bh

word1 WORD 0A69Bh

.code

MOVZX EAX, word1                       ; EAX = 0000A69Bh

MOVZX EDX, byte1                        ; EDX = 0000009Bh

MOVZX CX, byte1                          ; CX = 009Bh

 

MOVSX 명령 (부호가 있는)

 

소스 피연산자의 내용을 도착점 피연산자로 복사 후 16비트 혹은 32비트로 값을 부호 확장한다.

이 명령어는 부호가 있는 정수에만 사용된다. 3개의 변형이 있다.

 

MOVSX r32, r/m8

MOVSX r32, r/m16

MOVSX r16, r/m8

 

작은 피연산자의 최상위 비트를 취하고 이를 도착점 피연산자의 확장 비트에 반복적으로 복사하여 부호 확장을 한다.

예를 들어, 8비트 값 10001111b 가 16비트 도착점으로 이동한다면, 하위 8비트는 그대로 복사된다. 다음에 다음 그림에서

보는 것처럼 소스의 최상위 비트는 도착점의 상위 8비트에 복사된다.

 


다음의 예는 피연산자가 모두 레지스터일 때의 경우이다.

 

MOV BX, 0A69Bh

MOVSX EAX, BX                                       ; EAX = FFFFA69Bh

MOVSX EDX, BL                                       ; EDX = FFFFFF9Bh

MOVSX CX, BL                                         ; CX = FF9Bh

 

예제)  bbb.asm 파일

TITLE move
INCLUDE Irvine32.inc
.code
main PROC 
             MOV BX, 0A69Bh
             MOVSX EAX, BX
             MOVSX EDX, BL
             MOVSX CX, BL
             call DumpRegs 
             exit
main ENDP
END main