汇编语言基础之三 - 变量的访问和流程控制指令

时间:2021-07-22 01:25:58

访问变量

与其他等级的编程语言一样,汇编语言能够用许多方式来访问变量。变量有三种基本的存储方式。

1. 全局变量/静态变量- 在程序数据区(program data section)分配

2. 局部变量/参数- 在栈上分配

3. 堆变量- 在堆上分配

 

全局,静态变量

全局变量存储在一个固定的地址上(至少对于程序来说,他们是固定的)。访问这些变量的最通常的方式是在指令中明确指出那个固定的地址。

MOV    EAX,[1234134H]        ; loads EAX with value stored at location 12341234H

INC      DWORD PTR TEST2!_nCount ; increments DWORD variable nCount

注意,在symbolic信息可用的时候,debugger会去使用它。

 

局部变量,参数

局部变量和参数存在于栈上,并且是通过EBP(有时候是ESP)来访问的。优化过的代码通常会清除掉对栈基指针(frame pointer)的依赖,在这样的情况下ESP寄存器被用来访问局部变量,而EBP可以被用来做一个额外的通用寄存器来使用。当你使用一个标准栈基指针的时候,指令看起来应该是这样的。

MOV   EAX,[EBP+8]   ; load EAX with argument

MOV   EAX,[EBP-4]    ; load EAX with local variable

有一个记忆的小窍门,当EBP没有作为通用寄存器使用的时候,也就是绝大多数时候,当位移是正的时候,访问的是参数。当位移是负的时候,访问的是局部变量。

注意,典型的第一个传递给函数的参数是EBP+8

 

堆变量

堆变量存在于堆上,他们是通过指针来访问的。典型情况下需要不只一条指令来访问堆变量。

MOV   ESI, TEST2!_m_pFileList     ; load the pointer

MOV   EAX, [Esi+4]                         ; read second DWORD (pszName) in heap

另一个需要注意的是,大多数编译器会将经常访问的变量放到寄存器中,以便于提高访问速度。尤其是精简指令计算机。

 

 

执行流控制

控制流命令要不就是有条件的(条件满足的时候),要不就是无条件的。这些语句支持函数调用,if-then-else,switch case等高级的语言成分。

 

无条件跳转指令

1. JMP命令

    这个命令简单的设置EIP寄存器为下一条指令的地址。没有任何数据会被存储到栈上,并且不会设置任何标志位。JMP被用在固定的指令分支上。大多数的if-then-else语句族至少需要一条JMP指令。

2. CALL命令

    这条指令先存储EIP的值到栈上,然后设置EIP为下一条指令的地址。将EIP压栈允许程序在结束了函数调用之后,回来继续执行CALL语句后面的语句。

对于JMP和CALL指令来说,操作数可以是固定的地址,寄存器的值,或者一个指向分支地址的指针。

3. RET命令

    RET指令将当前栈上的值赋给EIP寄存器。该命令用来为传递给栈的参数修复栈指针。

4. INT命令

    当INT命令的操作数是一个中断号的时候,该指令会引发一个软件中断。这个与CALL指令差不多,不同之处是EFLAGS寄存器被压入栈中。还有,如果是在user mode中被调用,在切换到kernel mode时也会发生将EFLAG寄存器压栈的操作。中断函数结束的时候,随着RETI指令的执行,EFLAGS寄存器和EIP都会从栈中恢复。

 

条件跳转指令

1, LOOP Adress

    LOOP指令被用来实现高级语言中的循环。直到ECX(计数器)的值为0的时候,它才会走向分支地址。如果ECX不是0,那么ECX会被减一,然后继续循环操作。

XOR     EAX,EAX    ; clear EAX register

MOV    ECX, 5        ; load loop count

START:

ADD     EAX,1         ; add one to eax

LOOP  START

2. JNX,JE等等

    根据条件来跳转的指令会去判断所指定的条件是否为真,若果是就执行跳转。比如,JNZ(jump not zero),操作数中指定的地址直到ZERO标志位被设置为1的时候才会被转过去。这些指令主要被用在if语句块中。

XOR    EAX,EAX   ; clear eax

MOV    ECX,5

START:

ADD    EAX,1       ; add one to EAX

DEC    ECX          ; decrement loop counter

JNZ     START