Intel x86 Assembly Language & Microarchitecture
제어 흐름
수색…
무조건 점프
jmp a_label ;Jump to a_label
jmp bx ;Jump to address in BX
jmp WORD [aPointer] ;Jump to address in aPointer
jmp 7c0h:0000h ;Jump to segment 7c0h and offset 0000h
jmp FAR WORD [aFarPointer] ;Jump to segment:offset in aFarPointer
상대 근처 점프
jmp a_label 은 다음과 같습니다.
- 가까운
대상 논리 주소 의 오프셋 부분 만 지정합니다. 세그먼트는CS라고 가정합니다. - 상대적인
명령어 의미 론 은 다음 명령 주소 또는IP = IP + rel에서 점프 rel 바이트 1 앞으로입니다.
명령어는 EB <rel8> 또는 EB <rel16/32> 로 인코딩되며, 어셈블러는 가장 적합한 형식을 선택하며 일반적으로 더 짧은 형식을 선호합니다.
예를 들어 NASM jmp SHORT a_label , jmp WORD a_label 및 jmp DWORD a_label 어셈블러 별 오버라이드가 가능합니다.
절대 가까운 간접 점프
jmp bx 및 jmp WORD [aPointer] 는 다음과 같습니다.
- 가까운
목적지의 논리 주소의 오프셋 부분 만 지정합니다. 세그먼트는CS라고 가정합니다. - 절대 간접
명령의 의미는 reg 또는 mem 또는IP = reg,IP = mem의 주소로 점프합니다.
명령은 FF /4 로 인코딩되며, 메모리 간접적으로 피연산자의 크기는 다른 메모리 액세스마다 결정됩니다.
절대 멀리뛰기
jmp 7c0h:0000h :
멀리
논리적 주소의 두 부분 인 세그먼트와 오프셋을 지정합니다.absolute 명령의 의미는 주소 세그먼트 (offset 또는
CS = segment, IP = offset)로 점프합니다.
명령은 코드 크기에 따라 EA <imm32/48> 로 인코딩됩니다.
예를 들어, NASM jmp 7c0h: WORD 0000h 및 jmp 7c0h: DWORD 0000h 와 같은 일부 어셈블러에서 두 가지 형식 중에서 선택할 수 있습니다 jmp 7c0h: DWORD 0000h 는 첫 번째 및 두 번째 형식을 생성합니다.
절대 간접 멀리뛰기
jmp FAR WORD [aFarPointer] 는 다음과 같습니다.
far 논리 주소의 두 부분 인 세그먼트와 오프셋을 지정합니다.
Absolute indirect 명령의 의미는 mem 2 또는
CS = mem[23:16/32], IP = [15/31:0]저장된 세그먼트 : 점프로 점프합니다.
명령은 FF /5 로 인코딩되며 피연산자의 크기는 크기 지정자가있는 컨트롤러가 될 수 있습니다.
NASM에서 조금 비 직관적 그것들은 jmp FAR WORD [aFarPointer] 16시 16분 피연산자 및 jmp FAR DWORD [aFarPointer] 16시 32분 피연산자.
누락 된 점프
절대 근처
가까운 간접 점프로 에뮬레이션 가능.mov bx, target ;BX = absolute address of target jmp bx먼 친척
어쨌든 사용의 의미 또는 너무 좁은합니다.
1 부호가있는 오프셋을 지정하기 위해 두 개의 보수가 사용되므로 역방향으로 점프합니다.
크기 16시 16분 및 16시 32분의 off32 : off16 또는 seg16하십시오 seg16 할 수있다 2.
시험 조건
조건부 점프를 사용하려면 조건을 테스트해야합니다. 여기 에서 조건을 테스트하는 것은 플래그를 확인하는 행위에만 해당되며 실제 점프는 조건부 점프에서 설명됩니다.
x86은 각 명령어가 잠재적으로 설정할 수있는 플래그 세트를 보유하고있는 EFLAGS 레지스터에 의존하여 조건을 테스트합니다.
sub 또는 add 와 같은 산술 명령어와 xor and or and 같은 논리 명령어는 분명히 플래그를 설정합니다. 이는 CF , OF , SF , ZF , AF , PF 플래그가 해당 지침에 의해 수정됨을 의미합니다. 모든 명령어는 플래그를 수정할 수 있습니다. 예를 들어 cmpxchg 는 ZF를 수정합니다.
특정 명령어에 의해 수정 된 플래그를 확인하려면 항상 명령어 참조 를 확인하십시오 .
x86은 앞에서 언급 한 일련의 조건부 점프를 가지고 있는데, 이는 일부 플래그가 설정되거나 일부가 해제되거나 모두 인 경우에만 점프합니다.
국기
산술 및 논리 연산은 플래그를 설정할 때 매우 유용합니다. 예를 들어, sub eax, ebx )가 서명되지 않은 값을 갖고있는 경우,
| 깃발 | 설정시 | 취소 할 때 |
|---|---|---|
| ZF | 결과가 0 일 때 EAX - EBX = 0 ⇒ EAX = EBX | 결과가 0이 아닌 경우 EAX - EBX ≠ 0 ⇒ EAX ≠ EBX |
| CF | 결과가 MSb에 대해 수행해야하는 경우. EAX - EBX <0 ⇒ EAX <EBX | 결과가 MSb를 위해 나올 필요가 없는 경우. EAX - EBX ≮ 0 ⇒ EAX ≮ EBX |
| SF | 결과 MSb가 설정된 경우. | 결과 MSb가 설정 되지 않은 경우 . |
| 의 | 서명 된 오버플로가 발생했습니다. | 서명 된 오버 플로우가 발생하지 않은 경우 . |
| PF | 결과의 최하위 바이트에 설정된 비트 수가 짝수 일 때. | 결과의 최하위 바이트에 설정된 비트 수가 홀수 일 때. |
| AF | 낮은 BCD 숫자가 캐리를 생성 할 때. 비트 4 캐리입니다. | 낮은 BCD 숫자가 캐리를 생성하지 않은 경우. 비트 4 캐리입니다. |
비파괴 검사
sub 및 and 명령은 대상 피연산자를 수정하며 대상을 수정하지 않고 유지하기 위해 두 개의 추가 복사본 (저장 및 복원)이 필요합니다.
비파괴 검사를 수행하려면 cmp 및 test 지침이 있습니다. 연산의 결과가 무시되고 플래그 만 저장된다는 점을 제외하고는 상 대방과 동일합니다 .
| 파괴적인 | 비 파괴적인 |
|---|---|
sub | cmp |
and | test |
test eax, eax ;and eax, eax
;ZF = 1 iff EAX is zero
test eax, 03h ;and eax, 03h
;ZF = 1 if both bit[1:0] are clear
;ZF = 0 if at least one of bit[1:0] is set
cmp eax, 241d ;sub eax, 241d
;ZF = 1 iff EAX is 241
;CF = 1 iff EAX < 241
서명 된 테스트와 서명되지 않은 테스트
CPU는 값 1 을 등록하는 특별한 의미가 없으며, sign은 프로그래머 구성입니다. 부호있는 값과 부호없는 값을 테스트 할 때 차이점은 없습니다. 프로세서는 피연산자가 부호가 있거나 부호가없는 것으로 간주되어야하는 경우 일반 산술 관계 (같음,보다 작음,보다 큼 등)를 테스트하기에 충분한 플래그를 계산합니다.
1 2의 보수와 같은 특정 형식에서만 의미가있는 지침이 있지만. 이것은 소프트웨어에서 알고리즘을 구현할 때 많은 코드가 필요하므로 코드를보다 효율적으로 만드는 것입니다.
조건부 점프
플래그의 상태에 따라 CPU는 점프를 실행하거나 무시할 수 있습니다. 플래그를 기반으로 점프를 수행하는 명령어는 Jcc - Jump on Condition Code 1 이라는 일반 이름 아래에 있습니다.
동의어 및 용어
어셈블리 코드의 가독성을 향상시키기 위해 인텔은 동일한 조건 코드에 대해 몇 가지 동의어를 정의했습니다. 예를 들어, jae , jnb 및 jnc 는 모두 동일한 조건 코드 CF = 0 입니다.
명령어 이름은 언제 사용할지에 대한 매우 강력한 힌트를 줄 수 있지만, 유일한 의미있는 접근법은 테스트해야하는 플래그를 인식 한 다음 지침을 적절히 선택하는 것입니다.
인텔은 cmp 명령 후에 사용할 때 완벽하게 이해할 수있는 지침 이름을 제공했습니다. 이 토론의 목적을 위해, cmp 는 조건부 점프 전에 플래그를 설정했다고 가정합니다.
평등
ZF 가 설정되면 피연산자는 동일합니다. 그렇지 않으면 피연산자가 다릅니다. 평등을 테스트하려면 ZF = 1이 필요합니다.
je a_label ;Jump if operands are equal
jz a_label ;Jump if zero (Synonym)
jne a_label ;Jump if operands are NOT equal
jnz a_label ;Jump if not zero (Synonym)
| 교수 | 국기 |
|---|---|
je , jz | ZF = 1 |
jne , jnz | ZF = 0 |
보다 큰
부호없는 피연산자의 경우 carry가 필요하지 않은 경우, 즉 CF = 0 인 경우 대상이 소스보다 큽니다. CF = 0 일 때 피연산자가 같을 수 있으므로 테스트 ZF 가 모호해집니다.
jae a_label ;Jump if above or equal (>=)
jnc a_label ;Jump if not carry (Synonym)
jnb a_label ;Jump if not below (Synonym)
ja a_label ;Jump if above (>)
jnbe a_label ;Jump if not below and not equal (Synonym)
| 교수 | 국기 |
|---|---|
jae , jnc , jnb | CF = 0 |
ja , jnbe | CF = 0, ZF = 0 |
부호가있는 피연산자의 경우 서명 된 오버 플로우가없는 한 SF = 0 인지 확인해야합니다.이 경우 SF 가 반전됩니다. 부호있는 오버 플로우가 발생하지 않으면 OF = 0 이고, 그렇지 않으면 1이므로 SF = OF 인지 확인해야합니다.
엄격한 / 엄격하지 않은 테스트를 구현하는 데 ZF를 사용할 수 있습니다.
jge a_label ;Jump if greater or equal (>=)
jnl a_label ;Jump if not less (Synonym)
jg a_label ;Jump if greater (>)
jnle a_label ;Jump if not less and not equal (Synonym)
| 교수 | 국기 |
|---|---|
jge , jnl | SF = OF |
jg , jnle | SF = OF, ZF = 0 |
미만
위의 거꾸로 된 조건을 사용합니다.
jbe a_label ;Jump if below or equal (<=)
jna a_label ;Jump if not above (Synonym)
jb a_label ;Jump if below (<)
jc a_label ;Jump if carry (Synonym)
jnae a_label ;Jump if not above and not equal (Synonym)
;SIGNED
jle a_label ;Jump if less or equal (<=)
jng a_label ;Jump if not greater (Synonym)
jl a_label ;Jump if less (<)
jnge a_label ;Jump if not greater and not equal (Synonym)
| 교수 | 국기 |
|---|---|
jbe , jna | CF = 1 또는 ZF = 1 |
jb , jc , jnae | CF = 1 |
jle , jng | SF! = OF 또는 ZF = 1 |
jl , jnge | SF! = OF |
특정 플래그
각 플래그는 j<flag_name> 하여 개별적으로 테스트 할 수 있습니다. 여기서 flag_name 에는 후행 F (예 : CF → C , PF → P )가 없습니다.
이전에 다루지 않은 나머지 코드는 다음과 같습니다.
| 교수 | 깃발 |
|---|---|
js | SF = 1 |
jns | SF = 0 |
jo | OF = 1 |
jno | OF = 0 |
jp , jpe (e = 짝수) | PF = 1 |
jnp , jpo (o = 홀수) | PF = 0 |
하나 더 조건부 점프 (여분의 것)
하나의 특별한 x86 조건부 점프는 플래그를 테스트하지 않습니다. 대신 cx 또는 ecx 레지스터의 테스트 값 (현재 CPU 주소 모드가 16 또는 32 비트 임)을 기반으로하며 레지스터에 0이 있으면 점프가 실행됩니다.
이 명령어는 rep 와 유사한 명령보다 먼저 카운터 레지스터 ( cx/ecx )의 유효성을 검사하거나 loop 루프보다 먼저 검증하도록 설계되었습니다.
jcxz a_label ; jump if cx (16b mode) or ecx (32b mode) is zero
jecxz a_label ; synonym of jcxz (recommended in source code for 32b target)
| 교수 | 등록 (플래그가 아님) |
|---|---|
jcxz , jecxz | cx = 0 (16b 모드) |
jcxz , jecxz | ecx = 0 (32b 모드) |
1 또는 그런 것.
산술 관계 테스트
부호없는 정수
보다 큰
cmp eax, ebx
ja a_label
크거나 같음
cmp eax, ebx
jae a_label
미만
cmp eax, ebx
jb a_label
작거나 같음
cmp eax, ebx
jbe a_label
같은
cmp eax, ebx
je a_label
같지 않음
cmp eax, ebx
jne a_label
부호있는 정수
보다 큰
cmp eax, ebx
jg a_label
크거나 같음
cmp eax, ebx
jge a_label
미만
cmp eax, ebx
jl a_label
작거나 같음
cmp eax, ebx
jle a_label
같은
cmp eax, ebx
je a_label
같지 않음
cmp eax, ebx
jne a_label
a_label
위의 예제에서 a_label 은 테스트 된 조건이 "true"인 경우 CPU의 대상 대상입니다. 테스트 된 조건이 "거짓"인 경우 CPU는 조건부 점프 다음의 명령을 계속 수행합니다.
동의어
코드의 가독성을 높이기 위해 사용할 수있는 명령어 동의어가 있습니다.
예를 들어 ja 와 jnbe (점프가 아닌 점 이하) 점은 같은 명령입니다.
서명 된 컴패니언 코드에 서명 됨
| 조작 | 서명되지 않은 | 서명 됨 |
|---|---|---|
| > | ja | jg |
| > = | jae | jge |
| < | jb | jl |
| <= | jbe | jle |
| = | je | je |
| ≠,! =, <> | jne | jne |