0%

assembly/汇编intel与att

汇编intel与att

汇编有两种语法标准, 分别是intel, att语法

intel语法对应, intel x86_x64体系, x86系列CPU上
att语法对应, gcc objdump 默认格式, 多种CPU上可用(x86, power, VAX)

编译器有

  • gasm: .s文件
  • nasm: .asm文件
  • masm: .asm文件
  • fasm: .asm文件

intel att 区别

https://blog.csdn.net/goodcrony/article/details/92794938 ATT与Intel汇编代码格式

指令名
Intel, 内存操作数前用前缀byte prt, word ptr, dword ptr表大小
ATT, 指令都有字符后缀b, w, l, 表内存操作数的大小

Intel是 mov al, byte ptr foo
AT&T是 movb $foo, %al
movb 传送字节 (1 B = 8 bit)
movw 传送字 (2 B = 16 bit)
movl 传送双字 (4 B = 32 bit)
因为在许多机器上, 32位数都称为长字(long word)

指令顺序
Intel右->左
ATT左->右

Intel是 mov dst, src
ATT是 mov src, dst

寄存器名字, Intel不用前缀%

Intel是 esp
ATT是 %esp

寄存器中值 = 地址

Intel是 dword ptr [ebp+8]
ATT是 8(%ebp)

立即数, Intel不用前缀$
Intel十六, 二进制后缀hb
ATT十六进制立即数前缀0x

十进制数
Intel是 123
ATT是 $123
十六进制数
Intel是 123h
ATT是 $0x123

ATT直接跳转, (跳转目标: 指令内一部分编码)

jmp Label_1

ATT间接跳转, (跳转目标: 寄存器R, 存储器M中的值[代码地址])
‘*’后为操作数

jmp *%eax 寄存器%eax中的值 = 跳转目标
jmp *(%eax) %eax中的值 = 存储器M地址, 存储器M中的值 = 跳转目标

远跳转和远调用

ATT是 ljmp/lcall section,section,offset
Intel是 jmp/call far section:offset

远返回

ATT是 lret $stack-adjust
Intel是 ret far stack-adjust

Intel可多代码段程序
ATT不用多代码段程序, UNIX要求所有代码一个段seg

gasm

已有c文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <math.h>
#include <stdio.h>

int main(void) {
const double pi = acos(-1.0);
double r, h, s, v;
printf("radius, height = ");
scanf("%lf%lf", &r, &h);
s = 2.0 * pi * r * (r + h);
v = pi * r * r * h;
printf("面积 = %.2f\n", s);
printf("体积 = %.2f\n", v);
return 0;
}

对应gcc, 通过c文件, 生成s文件

1
2
3
4
5
6
7
8
dassein@pad:~/nasm_pjt$ gcc -E area_2019_sep_24.c > area_2019_sep_24.i
dassein@pad:~/nasm_pjt$ gcc -S area_2019_sep_24.i
dassein@pad:~/nasm_pjt$ gcc -c area_2019_sep_24.s
dassein@pad:~/nasm_pjt$ gcc area_2019_sep_24.o -o area_2019_sep_24
dassein@pad:~/nasm_pjt$ ./area_2019_sep_24
radius, height = 13 14
面积 = 2205.40
体积 = 7433.01

z直接通过c生成可执行文件

1
gcc -c area_2019_sep_24.c -o area_2019_sep_24

生成s文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
	.file	"area_2019_sep_24.c"
.section .rodata
.LC1:
.string "radius, height = "
.LC2:
.string "%lf%lf"
.LC3:
.string "\351\235\242\347\247\257 = %.2f\n"
.LC4:
.string "\344\275\223\347\247\257 = %.2f\n"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $64, %rsp
movq %fs:40, %rax
movq %rax, -8(%rbp)
xorl %eax, %eax
movsd .LC0(%rip), %xmm0
movsd %xmm0, -32(%rbp)
leaq .LC1(%rip), %rdi
movl $0, %eax
call printf@PLT
leaq -40(%rbp), %rdx
leaq -48(%rbp), %rax
movq %rax, %rsi
leaq .LC2(%rip), %rdi
movl $0, %eax
call __isoc99_scanf@PLT
movsd -32(%rbp), %xmm0
addsd %xmm0, %xmm0
movsd -48(%rbp), %xmm1
mulsd %xmm0, %xmm1
movsd -48(%rbp), %xmm2
movsd -40(%rbp), %xmm0
addsd %xmm2, %xmm0
mulsd %xmm1, %xmm0
movsd %xmm0, -24(%rbp)
movsd -48(%rbp), %xmm0
mulsd -32(%rbp), %xmm0
movsd -48(%rbp), %xmm1
mulsd %xmm1, %xmm0
movsd -40(%rbp), %xmm1
mulsd %xmm1, %xmm0
movsd %xmm0, -16(%rbp)
movq -24(%rbp), %rax
movq %rax, -56(%rbp)
movsd -56(%rbp), %xmm0
leaq .LC3(%rip), %rdi
movl $1, %eax
call printf@PLT
movq -16(%rbp), %rax
movq %rax, -56(%rbp)
movsd -56(%rbp), %xmm0
leaq .LC4(%rip), %rdi
movl $1, %eax
call printf@PLT
movl $0, %eax
movq -8(%rbp), %rcx
xorq %fs:40, %rcx
je .L3
call __stack_chk_fail@PLT
.L3:
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.section .rodata
.align 8
.LC0:
.long 1413754136
.long 1074340347
.ident "GCC: (Ubuntu 6.2.0-5ubuntu12) 6.2.0 20161005"
.section .note.GNU-stack,"",@progbits

nasm

用c2nasm.bash反汇编nasm已有c文件

1
./c2nasm.bash area_2019_sep_24.c

自动生成area_2019_sep_24.asm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
default rel
global main

extern __stack_chk_fail
extern __isoc99_scanf
extern printf
extern _GLOBAL_OFFSET_TABLE_

SECTION .text
main:
push rbp
mov rbp, rsp
sub rsp, 64
mov rax, qword [fs:abs 28H]
mov qword [rbp-8H], rax
xor eax, eax
movsd xmm0, qword [rel L_006]
movsd qword [rbp-20H], xmm0
lea rdi, [rel L_002]
mov eax, 0
call printf
lea rdx, [rbp-28H]
lea rax, [rbp-30H]
mov rsi, rax
lea rdi, [rel L_003]
mov eax, 0
call __isoc99_scanf
movsd xmm0, qword [rbp-20H]
addsd xmm0, xmm0
movsd xmm1, qword [rbp-30H]
mulsd xmm1, xmm0
movsd xmm2, qword [rbp-30H]
movsd xmm0, qword [rbp-28H]
addsd xmm0, xmm2
mulsd xmm0, xmm1
movsd qword [rbp-18H], xmm0
movsd xmm0, qword [rbp-30H]
mulsd xmm0, qword [rbp-20H]
movsd xmm1, qword [rbp-30H]
mulsd xmm0, xmm1
movsd xmm1, qword [rbp-28H]
mulsd xmm0, xmm1
movsd qword [rbp-10H], xmm0
mov rax, qword [rbp-18H]
mov qword [rbp-38H], rax
movsd xmm0, qword [rbp-38H]
lea rdi, [rel L_004]
mov eax, 1
call printf
mov rax, qword [rbp-10H]
mov qword [rbp-38H], rax
movsd xmm0, qword [rbp-38H]
lea rdi, [rel L_005]
mov eax, 1
call printf
mov eax, 0
mov rcx, qword [rbp-8H]
xor rcx, qword [fs:abs 28H]
jz L_001
call __stack_chk_fail
L_001: leave
ret

SECTION .data
SECTION .bss
SECTION .rodata align=8

L_002:
db 72H, 61H, 64H, 69H, 75H, 73H, 2CH, 20H
db 68H, 65H, 69H, 67H, 68H, 74H, 20H, 3DH
db 20H, 00H

L_003:
db 25H, 6CH, 66H, 25H, 6CH, 66H, 00H

L_004:
db 0E9H, 9DH, 0A2H, 0E7H, 0A7H, 0AFH, 20H, 3DH
db 20H, 25H, 2EH, 32H, 66H, 0AH, 00H

L_005:
db 0E4H, 0BDH, 93H, 0E7H, 0A7H, 0AFH, 20H, 3DH
db 20H, 25H, 2EH, 32H, 66H, 0AH, 00H, 00H

L_006: dq 400921FB54442D18H

附录: c2nasm.bash

先把objconv程序放到/bin中, 供cmd使用obconv

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/bin/bash
# thanks to http://stackoverflow.com/a/20743090
# thanks to https://github.com/diogovk/c2nasm
# install objconv: https://github.com/vertis/objconv
#
# $1: source code

set -e
C_FILE="$1"
BASE_NAME="${C_FILE%.*}"
O_FILE="$BASE_NAME.o"
NASM_FILE="$BASE_NAME.asm"
gcc -Werror=implicit-function-declaration -fno-asynchronous-unwind-tables -O0 -c -o "$O_FILE" "$C_FILE"
objconv -fnasm "$O_FILE" "$NASM_FILE"
sed -i 's|st(0)|st0 |g' "$NASM_FILE"
sed -i 's|noexecute| |g' "$NASM_FILE"
sed -i 's|execute| |g' "$NASM_FILE"
sed -i 's|: function||g' "$NASM_FILE"
sed -i 's|?_|L_|g' "$NASM_FILE"
sed -i -n '/SECTION .eh_frame/q;p' "$NASM_FILE"
sed -i 's|;.*||g' "$NASM_FILE"
sed -i 's/^M//g' "$NASM_FILE"
sed -i 's|\s\+$||g' "$NASM_FILE"
sed -i 's|align=1||g' "$NASM_FILE"
rm "$O_FILE"