汇编 - 过程

过程或子例程在汇编语言中非常重要,因为汇编语言程序的大小往往很大。 过程由名称来标识。 遵循该名称,描述了执行明确定义的工作的过程主体。 过程的结束由返回语句指示。

语法

以下是定义过程的语法 −

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)给出栈中的偏移量 部分。

堆栈实现具有以下特点 −

  • 只有wordsdoublewords可以保存到堆栈中,而不是字节。

  • 堆栈向相反方向增长,即向低内存地址增长

  • 栈顶指向栈中最后插入的一项; 它指向插入的最后一个单词的低字节。

正如我们讨论的那样,在将寄存器的值用于某些用途之前将其存储在堆栈中; 可以通过以下方式完成 −

; 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{|}
...
...