NASM汇编教程翻译04 第四讲 子程序

英文原版地址:NASM Assembly Language Tutorials - asmtutor.com

介绍子程序

子程序是函数,是可复用的一段代码,能被你的程序调用去执行各种可重复的任务。子程序使用标签声明,就像之前的章节中使用一样,然而我们不用JMP指令去到达它们,而是使用CALL指令代替。在运行函数后我们也不用JMP指令去返回我们的程序。从子程序返回我们使用RET指令代替。

为什么我们不用JMP指令进入子程序?

这对于我们编写能重复使用的子程序是好事。如果我们想在代码的任何地方使用子程序,我们不得不写一些逻辑去决定在代码中从哪开始跳转以及跳转回哪里,我们的代码将被不想要的标签搞乱。但是,如果我们使用CALL和RET,汇编使用被称作栈的东西来帮助我们解决这个问题。

介绍下栈

栈是一种特殊类型的内存。它和我们之前使用的内存类型相同,然而它特殊在被我们的程序使用。栈时后进先出的内存。你可以认为栈像厨房中的一叠盘子。放上去的最后一个盘子也是下次你拿起用的第一个盘子。

不过在汇编中的栈不是存盘子的,是存值的。你可以在栈中存很多东西,例如变量,地址或其他程序。当我们调用子程序时我们需要使用栈来暂存之后要复原的值。

为了安全,函数需要使用的任何寄存器应该使用PUSH指令将它当前的值放在栈上。在函数已经完成它的逻辑之后,这些寄存器可以用POP指令恢复它们的初始值。这意味着任何寄存器中的值在调用函数前后都将保持不变。如果你在我们的子程序中注意到这一点,我们可以调用函数而不用担心它们对我们的寄存器做什么修改。

CALL和RET指令也使用栈。当你调用一个子程序。你调用地址将从你的程序压入栈中。这个地址时RET指令从栈中弹出的,是这个程序跳转返回到你的代码的位置。这就是为什么你总是跳转到标签但是你应该用CALL调用函数。

使用下边的命令编译,链接然后执行这个程序 hello.asm

SECTION .data
msg     db      'Hello, brave new world!', 0Ah     ; 指定msg变量为你的消息字符串
 
SECTION .text
global  _start
 
_start:

	mov     eax, msg        ; 将字符串的地址存到EAX
    call    strlen          ; 调用函数计算字符串长度

	mov     edx, eax        ; 要写入的字节数,字符数加0ah
    mov     ecx, msg   		; 将消息的内存地址复制ECX寄存器
    mov     ebx, 1      	; 写到标准输出
    mov     eax, 4      	; 调用 SYS_WRITE (kernel opcode 4)
    int     80h
    
    mov     ebx, 0      	; 返回状态值0退出,无错误
    mov     eax, 1      	; 调用 SYS_EXIT (kernel opcode 1)
    int     80h

strlen:                     ; 这是我们声明的第一个函数
    push    ebx             ; 将EBX的值压入栈中保留,在这个函数中我们要使用EBX
    mov     ebx, eax        ; 将EAX中的地址传给EBX (都指向内存中相同的位置)
 
nextchar:
    cmp     byte [eax], 0   ; 将EAX指向的字节与0做比较 (0是字符串结束的分隔符)
    jz      finished        ; 跳转 (如果ZF标记被设置) 跳转到标签'finished'指向的代码
    inc     eax             ; EAX中的地址增加1字节 (如果ZF标记没有被设置)
    jmp     nextchar        ; 跳转到标签'nextchar'指向的代码
 
finished:
    sub     eax, ebx		; 将EAX中的地址减去EBX中的地址
    pop     ebx             ; 将栈中的值弹出到EBX中
    ret                     ; 返回函数被调用的地址

编译命令

nasm -f elf hello.asm

链接命令

ld -m elf_i386 hello.o -o hello

执行命令

./hello

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值