汇编语言16位随机整数填充数组代码分析(7)

 

 

来自于《Intel汇编语言》(第四版)第八章的一段程序。程序非常简单,以下为代码:

 

 

.data

count = 100

array WORD count DUP(?)

.code

push OFFSET array

push COUNT

call ArrayFill

 

 

ArrayFill PROC

             push ebp

             mov ebp,esp

             pushad

             mov esi,[ebp+12]             ; offset of array

             mov ecx,[ebp+8]              ; array size

             cmp ecx,0                         ; ECX < 0?

             jle L2                                ; yes : skip over loop

L1:

             mov eax,10000h              ; get random 0-FFFFh

             call RandomRange            ; from the link library

             mov [esi],eax

             add esi,TYPE WORD

             loop L1

L2:

             popad

             pop ebp

             ret 8                                 ; clean up the stack

ArrayFill ENDP

 

 

让我们来看一下代码:

 

首先定义了一个count常量和一个WORD类型(16位)的数组。

 

然后程序首先将数组的偏移地址和COUNT压入堆栈:

 

push OFFSET array

push COUNT

 

 

 

此时的堆栈框架如下图所示:

 

 

                             offset(array)       <----------     [EBP + 12]

                             count                  <----------     [EBP + 8] 

                             return address   <----------     [EBP + 4]

                             EBP                     <----------     [ EBP,ESP]

 

 

所以随后才会使用(全部相对于EBP来取地址):

 

             mov esi,[ebp+12]             ; offset of array

             mov ecx,[ebp+8]              ; array size

 

来取得数组的偏移地址和count,分别送到esi(数组游标)和ecx(数组大小)中去。

 

(保护模式下,堆栈上以4个字节为单位保存参数,所以参数的地址才分别为EBP+4,+8,+12)

 

之后的循环体中的代码主要如下:

 

             mov eax,10000h              ; get random 0-FFFFh

             call RandomRange            ; from the link library

             mov [esi],eax

             add esi,TYPE WORD

 

因为我们要为数组赋值16位随机整数,所以范围是 0到FFFFh,所以为eax中赋值10000h(1000h-1=FFFFh),之后调用作者Irvine的库函数RandomRange生成随机数,然后将此随机数放置到eax寄存器中,接着程序将此值赋值给[esi],然后esi接着移动到下一个数组元素位置。

 

这样便完成了使用16位随机整数填充数组的程序。

 

 

不过汇编语言中还有一个更方便的返回任意类型的间接操作数的偏移地址的伪指令,这就是LEA,LEA在获取堆栈参数的地址时特别有用。

 

下面的程序同样来自于《Intel汇编语言程序设计》,FillString使用随机的ASCII数字0~9来填充字符串:

 

FillString PROC USES eax  esi

      LOCAL string[20] : BYTE

      ;Create and fill a 20-bytes string with ASCII digits.

  

      lea esi , string                 ; load effective address

      mov ecx,20

L1: mov eax,10

      call RandomRange           ; AL = 0..9

      add al,30h                       ; Covert to  ASCII character

      mov [esi],al

      add esi,1

      Loop L1

      ret

FillString ENDP

 

这里使用lea方便的取得了局部数组变量的地址。

 

 

注意:string是一个间接操作数,因此下面的语句将会产生一个错误(MOV..OFFSET 只能用于直接操作数):

 

mov eax , OFFSET string           ; error

 

 

 

另外关于LEA与OFFSET,摘自原书:

LEA指令返回任意类型的间接操作数的偏移。由于间接操作数可能使用一个或多个寄存器,因此其偏移值必须在运行时计算。相反,汇编运算符OFFSET仅返回编译时的偏移常量

你可能感兴趣的:(设计模式,框架,UP)