来自于《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仅返回编译时的偏移常量。
分享到:
相关推荐
本书覆盖了数制、计算机结构、汇编语言基础、基本控制结构以及高级主题如位操作等,为读者提供了全面而深入的学习材料。 #### 数制 **1.1 数制** - **1.1.1 十进制** - 基于10的计数系统,使用0至9十个数字进行...
- **汇编代码**:编写汇编语言源代码。 - **编译C代码**:如果程序包含C语言部分,则需要将其编译为汇编代码。 - **连接目标文件**:将多个目标文件合并成一个可执行文件。 - **理解一个汇编列表文件**:编译器产生...
- **汇编代码**: 编写汇编语言源代码。 - **编译C代码**: 混合编程时需要编译C代码。 - **连接目标文件**: 将多个目标文件链接成可执行文件。 - **理解一个汇编列表文件**: 包含了编译过程中生成的信息,有助于调试...
- **编写汇编代码**: 使用文本编辑器编写汇编语言源代码。 - **编译**: 使用汇编器将汇编语言转换成机器语言的目标文件。 - **连接**: 将多个目标文件链接成一个可执行文件。 - **理解汇编列表文件**: 编译过程中...
在MASM(Microsoft Macro Assembler)环境中,汇编语言是一种底层编程语言,常用于系统级编程和优化性能关键的任务。本篇文章将详细讲解如何利用汇编语言在MASM平台上实现随机数的生成,并找到这些随机数中的最大值...
Java波浪文字制作方法及源代码 1个目标文件 摘要:Java源码,初学实例,波浪文字 Java波浪文字,一个利用Java处理字符的实例,可以设置运动方向参数,显示文本的字符数组,高速文本颜色,显示字体的 FontMetrics对象,...
- **表达式**: `Int(Rnd * 71) + 10` 生成的随机整数范围为 `[10, 80]`。 - **解析**: `Rnd` 是一个介于 `0` 和 `1` 之间的随机数,乘以 `71` 后再加上 `10`,最小值为 `10`,最大值为 `80`。 ### 9. 程序设计语言...
这个过程包括将S数组填充为0到255的整数序列,并根据密钥进行一系列的置换操作。 2. **主循环函数**:这是RC4算法的核心,包括两个指针i和j的更新以及数组元素的交换。这两个指针会在每次迭代中自增,并通过特定的...
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语言问题》结构...
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,...
7. .NET Framework组件:主要包括公共语言运行库(Common Language Runtime, CLR)和类库,提供运行托管代码的基础环境和支持多种编程语言的互操作性。 8. main方法定义:Java中的main方法可以有多种合法定义,如A...
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++标准库--------------------------------------...