1. addr.S
extern printf ; the C function to be called
%macro pabc 1 ; a "simple" print macro
section .data
.str db %1,0 ; %1 is first actual in macro call
section .text
mov rdi, fmt4 ; first arg, format
mov rsi, .str ; second arg
mov rdx, a ; a' address rather than its value
mov rcx, b ; b' address rather than its value
mov r8, [c] ; fifth arg
mov rax, 0 ; no xmm used
call printf ; Call C function
%endmacro
section .data ; preset constants, writable
align 16
a: dq 3 ; 64-bit variable a initialized to 3
b: dq 4 ; 64-bit variable b initializes to 4
fmt4: db "%s, a=%p, b=%p, c=%ld",10,0 ; format string for printf
section .bss ; uninitialized space
c: resq 1 ; reserve a 64-bit word
section .text ; instructions, code segment
global main ; for gcc standard linking
main: ; label
push rbp ; set up stack
lit5: ; c=5;
mov rax,5 ; 5 is a literal constant
mov [c],rax ; store into c
pabc "c=5 " ; invoke the print macro
addb: ; c=a+b;
mov rax,[a] ; load a
add rax,[b] ; add b
mov [c],rax ; store into c
pabc "c=a+b" ; invoke the print macro
subb: ; c=a-b;
mov rax,[a] ; load a
sub rax,[b] ; subtract b
mov [c],rax ; store into c
pabc "c=a-b" ; invoke the print macro
mulb: ; c=a*b;
mov rax,[a] ; load a (must be rax for multiply)
imul qword [b] ; signed integer multiply by b
mov [c],rax ; store bottom half of product into c
pabc "c=a*b" ; invoke the print macro
diva: ; c=c/a;
mov rax,[c] ; load c
mov rdx,0 ; load upper half of dividend with zero
idiv qword [a] ; divide double register edx rax by a
mov [c],rax ; store quotient into c
pabc "c=c/a" ; invoke the print macro
pop rbp ; pop stack
mov rax,0 ; exit code, 0=normal
ret ; main returns to operating system
2. compile
nasm -f elf64 addr.S
gcc -o addr.x addr.o
3. run
./addr.x
c=5 , a=0x601040, b=0x601048, c=5
c=a+b, a=0x601040, b=0x601048, c=7
c=a-b, a=0x601040, b=0x601048, c=-1
c=a*b, a=0x601040, b=0x601048, c=12
c=c/a, a=0x601040, b=0x601048, c=4
可以看到, a 的地址是 16 位对齐的, 而 b 的 不是。
4. 修改代码, 设置 b align 16 属性
section .data ; preset constants, writable
align 16
a: dq 3 ; 64-bit variable a initialized to 3
align 16
b: dq 4 ; 64-bit variable b initializes to 4
fmt4: db "%s, a=%p, b=%p, c=%ld",10,0 ; format string for printf
5. 重新编译运行
c=5 , a=0x601040, b=0x601050, c=5
c=a+b, a=0x601040, b=0x601050, c=7
c=a-b, a=0x601040, b=0x601050, c=-1
c=a*b, a=0x601040, b=0x601050, c=12
c=c/a, a=0x601040, b=0x601050, c=4
现在可以看到, a, b 的地址都是 16位对齐了。