来自于《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仅返回编译时的偏移常量。
分享到:
相关推荐
Java波浪文字,一个利用Java处理字符的实例,可以设置运动方向参数,显示文本的字符数组,高速文本颜色,显示字体的 FontMetrics对象,得到Graphics实例,得到Image实例,填充颜色数组数据,初始化颜色数组。...
3.2 使用我的编译器,下面的代码inti=7;printf("%d\n",i++*i++);打印出49。不管按什么顺序计算,难道不该是56吗? 3.3 对于代码inti=3;i=i++;不同编译器给出不同的i值,有的为3,有的为4,哪个是正确的? *3.4 ...
书中列出了C用户经常问的400多个经典问题,涵盖了初始化、数组、指针、字符串、内存分配、库函数、C预处理器等各个方面的主题,并分别给出了解答,而且结合代码示例阐明要点。 《你必须知道的495个C语言问题》结构...
Java波浪文字,一个利用Java处理字符的实例,可以设置运动方向参数,显示文本的字符数组,高速文本颜色,显示字体的 FontMetrics对象,得到Graphics实例,得到Image实例,填充颜色数组数据,初始化颜色数组。...
6 机器语言、汇编语言和高级语言 1.7 C语言与C++的历史 1.8 C++标准库 1.9 Java、Internet与万维网 1.10 其他高级语言 1.11 结构化编程 1.12 典型C++环境基础 1.13 C++与本书的一般说明 1.14 C++编程简介 ...
6 机器语言、汇编语言和高级语言 1.7 C语言与C++的历史 1.8 C++标准库 1.9 Java、Internet与万维网 1.10 其他高级语言 1.11 结构化编程 1.12 典型C++环境基础 1.13 C++与本书的一般说明 1.14 C++编程简介 ...
o 4.2 使用我的编译器,下面的代码 int i=7; printf("%d\n", i++ * i++); 返回 49?不管按什么顺序计算, 难道不该打印出56吗? o 4.3 对于代码 int i = 3; i = i++; 不同编译器给出不同的结果, 有的为 3, 有的为 4,...
3.2 使用我的编译器,下面的代码int i=7; printf("%dnn", i++ * i++); 返回49?不管按什么顺序计算, 难道不该打印出56吗? . . . . . . 13 3.3 对于代码int i = 3; i = i++; 不同编译器给出不同的结果, 有的为 3, 有...
支持静态链接其它编程语言(如C/C++、汇编等)编译生成的静态库(.LIB或.OBJ),但仅限于COFF格式,支持cdecl和stdcall两种函数调用约定。 使用说明如下:函数声明和调用方法与DLL命令一致;“库文件名”以.lib...
1.6 机器语言、汇编语言和高级语言--------------------------------------5 1.7 C语言与C++的历史--------------------------------------------------6 1.8 C++标准库--------------------------------------...