汇编模板
测试¶
一些书写习惯¶
仅供参考, 主要是自己好记
寄存器¶
ecx
: iedi
: 数组基地址eax
: 尽量不使用, 因为乘除计算时必须使用eax
, 寄存器冲突不好解决- 修改 :
imul 目标操作数, 源操作数
可以直接对其他寄存器使用乘法, - 但是除法的
idiv
没有这么简单
- 修改 :
ebx
,edx
,esi
: 随意
比较¶
- 比较习惯用有符号数的比较 (正如我们高级语言中常使用 int 而非 unsigned int)
l
--lessg
--greatere
--equaln
--not- 如
>= → jge
基础模板¶
文件模板¶
fori¶
- 注意不要重复使用寄存器, 如之前使用过 ecx, 可以在循环体前
push ecx
, 循环体后pop ecx
来暂存 ecx
fori+forj¶
again_i:
cmp i, 8
jge final_i
mov j, 0
again_j:
cmp j, 8
jge final_j
... ; forj循环体
inc j
jmp again_j
final_j:
inc i
jmp again_i
final_i:
函数模板(空)¶
函数模板–-void¶
myFun PROC ;; void myFun(int* arr, int n) input:<----函数传参时的的入栈顺序
;; return:void
; [ebp+4]: 调用函数位置的地址
; [ebp+8]: arr
; [ebp+12]: n
push ebp ; 暂存栈底寄存器
mov ebp, esp ; 修改栈底, 创建一个"栈帧"
pushad ; 存放所有寄存器
... ; 代码段
popad ; 恢复所有寄存器
pop ebp ; 恢复栈底寄存器
ret 8 ; 返回原函数, 并pop8字节(去除栈中的arr和n)
;; 也就是 传入2个4字节参数, 此时就ret 2*4(8)
myFun ENDP
函数模板—有返回值¶
myFun PROC ;; myFun(int* arr, int n) input:<----函数传参时的的入栈顺序
;; return:eax
; [ebp+4]: 调用函数位置的地址
; [ebp+8]: arr
; [ebp+12]: n
push ebp ; 暂存栈底寄存器
mov ebp, esp ; 修改栈底, 创建一个"栈帧"
sub esp, 4 ; 为返回值预留4个字节
pushad ; 存放所有寄存器
... ; 代码段
mov [ebp-4], eax ; 暂存返回值
popad ; 恢复所有寄存器
mov eax, [ebp-4] ; 保存返回值到eax
add esp, 4 ; 去除预留个4字节
pop ebp ; 恢复栈底寄存器
ret 8 ; 返回原函数, 并pop8字节(去除栈中的arr和n)
;; 也就是 传入2个4字节参数, 此时就ret 2*4(8)
myFun ENDP
常用函数¶
打印数组¶
include irvine32.inc
.data
arr dd 1, 2, 3, 4, 5, 6, 7, 8, 9
n dd 9
space db " ", 0
.code
;主函数
main PROC
push n
push offset arr
call print
exit
main ENDP
print PROC ;; void print(int* arr, int n) input:<----入栈顺序
;; return:void
; [ebp+4]: 调用函数位置的地址
; [ebp+8]: arr
; [ebp+12]: n
push ebp ; 暂存栈底寄存器
mov ebp, esp ; 修改栈底, 创建一个"栈帧"
pushad ; 存放所有寄存器
mov ecx, 0 ; exc:i
mov edi, [ebp+8] ; edi:arr
again:
cmp ecx, [ebp+12]
jge final
mov eax, [edi+4*ecx]
call writeint
lea edx, space
call writeString
inc ecx
jmp again
final:
call crlf
popad ; 恢复所有寄存器
pop ebp ; 恢复栈底寄存器
ret 8 ; 返回原函数, 并pop8字节(去除栈中的arr和n)
;; 也就是 传入2个4字节参数, 此时就ret 2*4(8)
print ENDP
end main