어셈블리언어는 Intel과 AT&T 두 가지 문법을 가지고 있다.
같은 exe를 IDA와 GDB를 통해서 디스어셈블했는데 서로 오퍼랜드 위치가 반대여서 당황했다.
학교에서는 GDB에 나오는 방식의 어셈블리 언어를 배웠는데 IDA에서는 내가 생각했던 오퍼랜드 위치가 반대여서 혼동이 와서 찾아봤더니 두 가지 문법 차이가 있었고
IDA는 Intel 문법을 채택하고 있고 GDB는 AT&T 문법을 채택하고 있었습니다.
오퍼랜드 위치 차이
이 부분이 내가 당황했던 부분
Intel 문법에서는 목적지 오퍼랜드가 앞에 원본 오퍼랜드가 뒤에 위치하지만
AT&T 문법에서는 그 반대로 위치합니다.
Intel 문법
sub rsp, 50h
AT&T 문법
sub $0x50,%rsp
메모리 오퍼랜드
메모리 오퍼랜드 표기에서도 차이점이 있습니다.
Intel 문법의 경우는 [
과 ]
사이에 레지스터가 위치하지만,
AT&T 문법에서는 (
과)
사이에 레지스터가 위치합니다.
Intel 문법
cmp [rbp+var_4], 0
AT&T 문법
cmpl $0x0,-0x4(%rbp)
접두사 규칙
Intel 문법에서는 어떠한 접두사도 붙이지 않습니다.
그러나 AT&T 문법의 경우 레지스터
앞에는 %
를 붙이고 상수(값)
앞에는 $
가 붙습니다.
접미사 규칙
AT&T 문법에서는 정해진 규칙에 따라 접미사가 붙으며 각각의 접미사는 고유의 의미를 가집니다.
l
은 long
을 w
는 word
를 b
는 byte
를 각각의 의미합니다.
반면 Intel 문법에서는 접미사를 사용하지 않고 dword ptr
, qword ptr
처럼 의미있는 문장을 그대로 사용합니다.
여기서 dword는 long과 같은 크기를 가집니다.
상수 표현
Intel 문법에서는 16진수 상수를 표현할 때 숫자뒤에 h
를 붙이지만 AT&T 문법에서는 앞에 $0x
를 붙입니다.
Intel 문법
50h
AT&T 문법
$0x50
명령어 수행 문법
학교에서는 AT&T 방식으로 배워서 주소 계산이 헷갈렸는데 Intel은 완전 직관적
Intel에서는 Segreg: [base+index*scale+disp]
로 표현되는 것이 AT&T에서는
%Segreg: disp(base,index,scale)
와 같이 표현됩니다. Intel측이 확실히 직관적이라고 느낄 수 있습니다.
Intel 문법
mov eax, [ebx+20h]
add eax,[ebx+ecx*2h]
sub eax, [ebx+ecx*4h-20h]
AT&T 문법
movl 0x20(%ebx), %eax
addl (%ebx,%ecx,0x2), %eax
subl -0x20(%ebx, %ecx, 0x4), %eax
확실히 Intel 문법이 직관적으로 주소 값을 표기한다고 볼 수 있습니다.
참고한 블로그
https://blog.naver.com/ryutuna/100136727248