汇编小习题

汇编你还想及格?

你始终得以怀疑的态度去看待事情,做好最坏的打算。

1. 注释下面代码

Title Hello Word
.386 ;使用80386指令集
.model flat, stdcall;内存模型为平坦模型,子程序采用stdcall约定
.stack 4096;为运行时堆栈分配4096空间
ExitProcess proto , dwExitCode:DWORD;为过程创建过程原型
;过程原型声明了过程的名称和参数列表。
DumpRegs proto
.data
gga label word ;不占空间
ggb dd 12345678h,87654321h;占4*2字节
;低78 56 34 12 21 43 65 87高 
ggc dword "abcd" ; 占4*1字节
ggd=1234h;不占空间,或者说所占空间不连着ggc
ggf equ 12h;不占空间,或者说所占空间不连着ggc
ggg byte 10 dup("abc");占用1*10*3字节
ggh dd 10h,3 dup(50),20;占用4*5字节
ggi db 2 dup(?);占用1*2字节
listsize = $-gga ;64=0x40

.code
Main proc
	mov ax,gga;ax=5678h
	mov ebx,[ggb+2];ebx=43211234h,内存中的高位放在ebx高位
	xor edx,edx;清零
	mov edx,listsize;40h
	call dumpregs;打印寄存器
	invoke ExitProcess,0;push 0  ;call   ExitProcess
Main endp
end main

 

 

2. 算术运算

var1 word -16

原码1000 0000 0001 0000

补码1111 1111 1111 0000

十六进制:FFF0

对应的二进制数是1111 1111 1111 0000。

3.根据以下伪代码画出执行完push ebp后的堆栈图。

Push 10h
Push 20h
Push 30h
Call func1

func1 proc
    push ebp
    mov ebp,esp
    sub esp,8;为局部变量保留空间
    mov DWORD PTR [ebp-4],10 ;存放局部变量x 
    mov dword ptr [ebp-8],20 ;y
    movzx eax,[ebp+8];30h
    mov esp,ebp
    pop ebp
    ret
func1 endp

4. 要求编写汇编代码实现以下要求。(难)

(1)接受用户输入四位字符串,如"4513"

(2)对字符串进行冒泡排序

(3)以二进制形式输出到控制台。比如1345输出0001001101000101。

(4)在下面代码空余部分书写。

.386
.model flat, stdcall
.stack 4096
ExitProcess proto , dwExitCode:DWORD

.data

.code
Main proc

  invoke ExitProcess,0
Main endp
End main

提示:可以使用Writechar(al传递参数),ReadChar(al返回)。

解:本题有一定难度,Readchar容易读到缓冲区的东西,我们得用ReadString。本题最好不要用高级过程,不然堆栈平衡容易出错。

.386
.model flat, stdcall
.stack 4096
ExitProcess proto , dwExitCode:DWORD
ReadString proto;ecx存读取的个数(类似C语言,空格作为结束符),edx存偏移地址
WriteChar proto;将al的值打印
Crlf proto;换行
.data
str1 byte 5 dup(0)
count dword 5;ReadString最后一位是空格
str2 word 8;二进制1000

.code
Main proc

mov edx,offset str1
mov ecx,count 
call ReadString
mov ecx,4
dec ecx
L1:push ecx;冒泡排序,建议直接背模板
   lea esi,str1;运行时取str1地址
   L2:mov eax,[esi]
   mov ebx,[esi+1]
   and ebx,0FFh;保留最后一个字节
   and eax,0FFh
   cmp ebx,eax
   jl L3
   xchg eax,ebx;交换寄存器的值
   mov [esi],al
   mov [esi+1],bl

   L3:add esi,1
   loop L2
   pop ecx
loop L1
mov ebx,dword ptr str1

mov ecx,4
L4:mov ax,str2
   push ax
   push ecx
   mov ecx,4

   rol ebx,8;循环左移8位
   mov dx,bx
   and dx,0FFh
   sub dx,30h;数字的ascii码-30h就是数字

   L5:push dx;push至少2个字节(有点奇怪)
   mov al,30h
   and dl,byte ptr str2;强制类型转换
   cmp dl,1
   jb L6
   mov al,31h
   L6:call WriteChar
   shr str2,1;逻辑右移1位
   pop dx
   loop L5

   pop ecx;注意pop顺序
   pop ax
   mov str2,ax
loop L4
call Crlf
invoke ExitProcess,0
Main endp
End main

5. 名词解析

数据传送,寻址

inc,dec不影响进位标志。

mov指令:两操作数尺寸一致,不能同时为内存操作数,目的操作数不能是CS,EIP,IP,立即数不能直接送给段寄存器。

xchg:交换两个操作数的内容

neg:取反

movsx:带符号扩展的传送

movzx:零扩展并传送,只用于无符号整数

align:将变量对齐到边界,如align 4 对齐到双字边界

label:可以插入一个标号,并定义大小,但不为标号分配空间 (或者说占用的空间在其他地方)

ptr:覆盖一个已经被声明的操作数大小

type操作符:返回变量单个元素大小,如type var1

lengthof:计算数组中元素个数,如lengthof array1

sizeof:相当于lengthof返回值*type返回值

lahf:将标志寄存器的低字节复制到ah中。

sahf:将ah复制到标志寄存器的低字节中。

dup:表示变量占用的字节空间

equ:M1 EQU 10*10 把符号名称与一个整数表达式或文本连接起来。(占用的空间在其他地方)

条件处理

not指令不影响标志。

test:两操作数and运算,但不影响目的操作数

loopz:loop if zf=1

ja:基于无符号数比较,大于则跳转

jb:基于无符号数比较,小于则跳转

jg:基于有符号数比较,大于则跳转

jl:基于有符号数比较,小于则跳转

高级过程

addr:在汇编阶段获取偏移地址、只能配合invoke使用,取到传入全局变量参数的偏移地址;

offset:在汇编阶段获取偏移地址、只能取到全局变量的偏移地址;

lea:在执行阶段获取偏移地址,可以获取全局变量、局部变量等采用直接寻址、间接寻址和变址寻址的操作的地址;

stdcall:传参的方式是堆栈传参、传参的顺序是从右到左、堆栈平衡(清理)工作由子函数(被调用者)来完成;

cdecl:传参的方式是堆栈传参、传参的顺序是从右到左、堆栈平衡(清理)工作由父函数(调用者)来完成;

proto:声明过程原型。

proc:定义函数(过程)。

uses:保存子函数用到的寄存器的值,相当于 push和pop两条指令的功能

local:声明一个或多个变量,并赋予大小属性。必须紧跟在proc后func1 proc LOCAL var1:byte,arr1[10]:dword,arr2:ptr word

enter:可以简化堆栈帧的建立过程,带有两个参数,相当于 push ebp、mov ebp、esp和sub esp、imm等3条指令的功能;

leave:可以简化堆栈帧的销毁过程,相当于mov esp、ebp和pop ebp等2条指令的功能;

invoke:调用函数的另外一种方式,通过该指令调用的函数在调用之前必须进行声明,其本质相当于 push 和 call 的组合。

call:调用过程

ret:指令从堆栈把返回地址弹回到指令寄存器。

push:先减esp再压栈。

pop:先出栈再加esp。

pushfd:将EFL寄存器内容压入堆栈

pushad:按EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI顺序,将所有32位通用寄存器的值压入堆栈

pusha:按AX,CX,DX,BX,SP,BP,SI,DI顺序,将16位通用寄存器的值压入堆栈


整数算术运算

imul:有符号整数乘法

idiv:有符号整数除法

CBW:符号扩展指令,字节转字

CWD:字转双字,dx每位按ax符号位置位

CDQ:双字转四字

ADC:带进位加法,将源操作数和进位标志的值都加到目的操作数中。 adc d,s ;d=d+s+cf

SBB:带借位减法:从目的操作数中减去源操作数和进位标志的值。

stc:cf置1

clc:cf清0

shl:逻辑左移

sal:算数左移

rol:循环左移

rcl:带进位循环左移

shld:双精度左移

串处理

cmps和scas指令会对标志位有影响。

movs,lods,stos不会影响标志位。

std:df置1

cld:df置0

rep:重复前缀,以ecx作循环控制知道ecx减到0为止.

repz/repe:ecx>0且zf=1

movsb/movsw/movsd:将数据从esi指向的内存位置复制到edi指向的内存位置。这两个寄存器自动地递增或递减(根据方向标志的值,df=0则递增)。

cmpsb/cmpsw/cmpsd:将ESI指向的内存操作数与EDI指向的内存操作数进行比较。根据方向标志的值决定ESI和EDI递增或递减。

scasb/scasw/scasd:分别将al/ax/eax中的值与edi寻址的一个byte/word/dword进行比较。

stosb/stosw/stosd:分别将al/ax/eax中的值存入edi指向的内存偏移量处。根据方向标志的值决定EDI递增或递减。

lodsb/lodsw/lodsd:分别从edi指向的内存地址向al/ax/eax装入byte,word,dword。根据方向标志的值决定esi递增或递减。

mov esi,offset source
mov edi,offset target
cld
mov ecx,lengthof source
repe cmpsd


 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值