汇编 - 过程
过程或子例程在汇编语言中非常重要,因为汇编语言程序的大小往往很大。 过程由名称来标识。 遵循该名称,描述了执行明确定义的工作的过程主体。 过程的结束由返回语句指示。
语法
以下是定义过程的语法 −
proc_name: procedure body ... ret
使用 CALL 指令从另一个函数调用该过程。 CALL 指令应将被调用过程的名称作为参数,如下所示 −
CALL proc_name
被调用过程使用 RET 指令将控制权返回给调用过程。
示例
让我们编写一个名为 sum 的非常简单的过程,它将 ECX 和 EDX 寄存器中存储的变量相加,并将总和返回到 EAX 寄存器中 −
section .text global _start ;must be declared for using gcc _start: ;tell linker entry point mov ecx,'4' sub ecx, '0' mov edx, '5' sub edx, '0' call sum ;call sum procedure mov [res], eax mov ecx, msg mov edx, len mov ebx,1 ;file descriptor (stdout) mov eax,4 ;system call number (sys_write) int 0x80 ;call kernel mov ecx, res mov edx, 1 mov ebx, 1 ;file descriptor (stdout) mov eax, 4 ;system call number (sys_write) int 0x80 ;call kernel mov eax,1 ;system call number (sys_exit) int 0x80 ;call kernel sum: mov eax, ecx add eax, edx add eax, '0' ret section .data msg db "The sum is:", 0xA,0xD len equ $- msg segment .bss res resb 1
当上面的代码被编译并执行时,会产生以下结果 −
The sum is: 9
堆栈数据结构
堆栈是内存中类似数组的数据结构,可以在其中存储数据,也可以从称为堆栈"顶部"的位置删除数据。 需要存储的数据被"推入"堆栈,而要检索的数据则从堆栈"弹出"。 堆栈是一种后进先出的数据结构,即先存储的数据最后取出。
汇编语言提供了两种堆栈操作指令:PUSH 和 POP。 这些指令的语法如下 −
PUSH operand POP address/register
堆栈段中保留的内存空间用于实现堆栈。 寄存器SS和ESP(或SP)用于实现堆栈。栈顶,指向最后插入栈中的数据项,由 SS:ESP 寄存器指向,其中 SS 寄存器指向栈段的开头,SP(或 ESP)给出栈中的偏移量 部分。
堆栈实现具有以下特点 −
只有words或doublewords可以保存到堆栈中,而不是字节。
堆栈向相反方向增长,即向低内存地址增长
栈顶指向栈中最后插入的一项; 它指向插入的最后一个单词的低字节。
正如我们讨论的那样,在将寄存器的值用于某些用途之前将其存储在堆栈中; 可以通过以下方式完成 −
; Save the AX and BX registers in the stack PUSH AX PUSH BX ; Use the registers for other purpose MOV AX, VALUE1 MOV BX, VALUE2 ... MOV VALUE1, AX MOV VALUE2, BX ; Restore the original values POP BX POP AX
示例
以下程序显示整个 ASCII 字符集。 主程序调用名为display的过程,该过程显示ASCII字符集。
section .text global _start ;must be declared for using gcc _start: ;tell linker entry point call display mov eax,1 ;system call number (sys_exit) int 0x80 ;call kernel display: mov ecx, 256 next: push ecx mov eax, 4 mov ebx, 1 mov ecx, achar mov edx, 1 int 80h pop ecx mov dx, [achar] cmp byte [achar], 0dh inc byte [achar] loop next ret section .data achar db '0'
当上面的代码被编译并执行时,会产生以下结果 −
0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} ... ...