使用YASM编程 - 05

我们一般实现C语言的 汉诺塔的时候,代码类似下面

;
;void hanno(a,b,c,n)
;{
;       if(n==1)
;       {
;          printf("%c %c\n",a,c);
;          return ;
;       }
;       hanno(a,c,b,n-1)
;       hanno(a,b,c,1)
;       hanno(b,a,c,n-1)
;}

在汇编语言中处理比较麻烦的是参数的处理和局部变量,全局变量的处理。
这里将每个参数都定义为宏,每个宏都代表[ebp+8] [ebp+12]
然后我们就可以使用这些宏了。
未来我们用一个宏来定义这些参数,然后就能很方便的使用。
1 这里并没有将原来的Invoke 宏实现加载进来
2 这里也没有将 EBP 内容保存恢复等封装
3 这里也没有将局部变量保存和恢复封装。
我们展示一下基本的递归的实现和变量的使用.
栈的内容
| |
|新的栈底|
| | ————— 表示变量区域,变量区域必须保留
| | | 否则会被其他的函数调用覆盖
| |—————
| ebp |
|返回地址|
|第一个参数|
|第二个参数|
|第三个参数|
|…|

而ebp指向前面的ebp … 当前ebp可以理解为一个队列的头,如果有一个新的函数调用那么就会将现在的ebp插入到队列头上
这个队列结构类似
struct stack_ebp{
stack_ebp next*;
void* addr;
void* param[0]; // 这个是参数列表
}
下面的汇编就使用了上面的知识 。
下面这段代码是编译 .asm 文件,并且声称对应的obj pdb exe 文件

rem build_asm.bat
rem build_asm fibo
rem 编译和链接
vsyasm -f win32 -g cv8 -o %1.obj %1.asm
link /entry:start /DEBUG /PDB:%1.pdb /subsystem:console /debug /machine:x86 /out:%1.exe /release /verbose:lib /libpath:C:\masm32\lib kernel32.lib user32.lib %1.obj msvcrt.lib  
bits 32
[section .data]
format: db "%c -> %c",0x0a,0
[section .text]
global start
global hanno
extern _printf
extern _scanf
start:

jmp code
var_a : db 'a'
var_b : db 'b'
var_c : db 'c'
[section .data]
input_num_format: db "%d",0
var_n : dd 0
promot_string: db "input a num:",0
[section .text]
code:
    push promot_string
    call _printf
    add esp,4

    push var_n
    push input_num_format
    call _scanf
    add esp,8

    movsx eax,BYTE [var_n]
    push eax
    movsx eax,BYTE [var_c]
    push eax
    movsx eax,BYTE [var_b]
    push eax
    movsx eax,BYTE [var_a]
    push eax
    call hanno
    add esp,16
ret

[section .text]
;输入 a,b,c,n 
; a - 字母
; b - 字母
; c - 字母
; n - 多少个盘子
;
;
;a - [ebp+8]
;b - [ebp+0x0c]
;c - [ebp+0x10]
;n - [ebp+0x14]
hanno:
%define hanno_a DWORD [ebp+8]
%define hanno_b DWORD [ebp+12]
%define hanno_c DWORD [ebp+16]
%define hanno_n DWORD [ebp+20]
    push ebp
    mov ebp,esp

    cmp hanno_n,1
    jz is_one
    mov eax,hanno_n
    dec eax

    push eax
    push hanno_b
    push hanno_c
    push hanno_a
    call hanno
    add esp,16

    push 1
    push hanno_c
    push hanno_b
    push hanno_a
    call hanno
    add esp,16

    mov eax,hanno_n
    dec eax
    push eax
    push hanno_c
    push hanno_a
    push hanno_b
    call hanno
    add esp,16

    pop ebp
    ret
is_one:
    push hanno_c
    push hanno_a
    push format
    call _printf
    add esp,12
    pop ebp
    ret

猜你喜欢

转载自blog.csdn.net/justin_bkdrong/article/details/77921754