本篇介绍
本篇先介绍一个GUI工具,用来查看寄存器和内存,再介绍下代码跳转。
DDD
首先先安装之:
代码语言:javascript复制sudo apt install ddd
再写一段如下的代码:
代码语言:javascript复制 ;; hello.asm
section .data
bNum db 123
wNum dw 12345
dNum dd 1234567890
qNum1 dq 1234567890123456789
qNum2 dq 123456
qNum3 dq 3.14
section .bss
section .text
global main
main:
push rbp
mov rbp, rsp
mov rax, -1
mov al, byte [bNum]
xor rax,rax
mov al,byte [bNum]
mov rax, -1
mov ax, word [wNum]
xor rax,rax
mov ax, word [wNum]
mov rax, -1
mov eax, dward [dNum]
mov rax, -1
mov rax, qword [qNum1]
mov qword [qNum2], rax
mov rax, 123456
movq xmm0, [qNum3]
mov rsp,rbp
pop rbp
ret
保存成 hello.asm, make后执行ddd hello,结果如下:
image.png
可以发现ddd 就是带有GUI的gdb,先在main上打个断点,点击run,这时候就会停到main上。
image.png
执行到第20行会发现一个问题,将bNum赋值给al了,可是rax的值是0xffffffffffffff7b
,并不是bNum,原来是只把低八位赋值了,但并没有将高56位清零。继续mov 一个字也一样,有48位没有清空。当用32位给64位赋值的时候,就会发现rax的高32位被清零了。
因此可以得出以下关键结论:
- 用8,16位数字给64位寄存器赋值,不会清空高位
- 用32位数字给64会寄存器赋值,会自动清空高位
sasm
接下来安装一个汇编的IDE,sudo apt install nsam
:
接下来建一个工程:
image.png
代码如下:
代码语言:javascript复制%include "io.inc"
extern printf
section .data
number1 dq 42
number2 dq 41
fmt1 db "NUMBER1 >= NUMBER2",10,0
fmt2 db "NUMBER1 < NUMBER2",10,0
section .bss
section .text
global CMAIN
CMAIN:
push rbp
mov rbp, rsp; for correct debugging
;write your code here
mov rax, [number1]
mov rbx, [number2]
cmp rax, rbx
jge greater
mov rdi,fmt2
mov rax,0
call printf
jmp exit
greater:
mov rdi, fmt1
mov rax,0
call printf
exit:
mov rsp, rbp
pop rbp
ret
jmp指令结果会体现在eflags上,比如ZF(zero flag),SF(sign flag),OF(overflow flag)等位。具体区别如下:
image.png
再来一段循环代码:
代码语言:javascript复制%include "io.inc"
extern printf
section .data
number dq 5
fmt db "The sum from 0 to %ld is %ld", 10,0
section .bss
section .text
global CMAIN
CMAIN:
push rbp
mov rbp, rsp; for correct debugging
;write your code here
mov rcx, [number]
mov rax, 0
bloop:
add rax, rcx
loop bloop
mov rdi, fmt
mov rsi, [number]
mov rdx, rax
mov rax,0
call printf
exit:
mov rsp, rbp
pop rbp
ret
这儿引入了loop指令,每次循环都会将rcx 减1。这时候我们就完成了ddd和sasm的初步学习。