概要
- 无条件转移
- 条件转移、比较指令和if结构
- 循环结构的实现
- for循环
- 作业
无条件转移
主要语句:
jmp StatemenLabel(自定义名字)
代码部分
StagemenLabel:
跳转执行部分
例子
小补充
- 向后引用:jmp转移控制到jmp语句本身之前。
- 向前引用:jmp转移控制到jmp语句本身之后。
怎么实现:jmp指令有两种指令(相对短(short),相对近(near)),它们都可以改变指令指针寄存器EIP中的值。注意是指令指针,因此,要执行的下一条指令来自于一个新的地址,而不是紧跟在当前指令后的地址。每条相对的转移指令包含相对jmp指令本身的目标位移量,这个位移量加上下一条指令的地址就是转移的目标地址(转移的目标地址=相对jmp指令的相对位移量+下一条指令的地址)。偏移量是一个有符号数。对于向前引用,它是正数,对于向后引用,它是负数。
间接转移指令:
jmp edx
使用32位地址作为目标地址,而不是位移量。但是这个地址并没有写在指令中,而是保存在寄存器中。(相关可以参照上一条博客,寻址方式)
条件转移、比较指令和if结构
条件转移指令可以实现if结构、其他选择结构以及循环结构。
格式如下:
j- 目标语句#'j' = juage,'-' = 其他比较字符的缩写
等下会一一介绍,所以学好英语很重要!
解释:如果条件满足,则发生转移;否则执行下一条指令(条件转移后面的语句)。
原理
条件转移指令的原理,就是判断标志寄存器中的标识来设置的,如
jz endwhile
如果零标志ZF为1,则转移到有标号endwhile的语句,否则执行后面的语句。另外,条件转移指令不改变任何标志位,只根据已经设置好的标识符做出反应。(标识符可参照以前博客标识符)
以上已经介绍了条件转移的大致原理,那么我们做到改变表示符,或者说更加符合高级语言呢?
如:
for i in range(0,100):
print(i)
if i<10 and i>0:
print(i)
在汇编语言中,有专门的比较操作符:
cmp
格式如下:
cmp 操作数1 操作数2
简单来说,就是使用操作数1去减操作数2(类似于sub),但是它并不会改变操作数的值(sub会),它只会根据结果改变标志位的值。参照表如下(能理解就行):
另外还有几个不常用的指令:
set#设置
reset#重置
它们可以设置或者清零。
紧接着,再详细说一下条件转移指令,先看下图:
是不是看着就很多?不怕怎么靠英语来记:
a:大于
b:小于
(这两个是真的没想明白,可能是无符号的原因吧)
j:juage(判断)
g:greater(大于)
n:no(不)
l:less(小于)
e:equal(等于)
z:zero(0)
s:sign(符号,正负)
c:carry(进位)
p:parity(奇偶)
o:overflow(溢出)
大概就是这些因为,那么我们再试一下:
jnle:开始组合,juage no less equal:判断不小于等于,则跳转,这样是不是好理解多了?
cmp和j-的组合使用
cmp eax,100
ja bigger
解释:判断eax是否大于100,是则跳转到bigger部分的指令,否则向下执行。
例子
循环结构的实现
其实原理和上面一样(通过cmp,jmp实现跳转),所以直接放图:
1.
2.
3.
for循环
loop statementLabel
其中statementLabel是距离loop语句较短偏移量的语句标号(向前128字节或者向后127字节)
loop指令执行以下动作:
- ECX中的值减少1
- 如果ECX中新的值是0,那么继续执行循环指令下面的语句
- 如果ECX中新的值不是0,那么执行转移指令到statementLabel
-
同时,我们完全可以用刚刚的知识实现这个循环:
作业
- 从键盘输入一个数字,转换成数值后,求解其绝对值,并显示结果在屏幕上。
;Program:转化
;Author:龙文汉
;Date:2020.11
.386
.MODEL FLAT
ExitProcess PROTO NEAR32 stdcall, dwExitCode:DWORD
INCLUDE io.h ; header file for input/output
cr EQU 0dh ; carriage return character
Lf EQU 0ah ; line feed
.STACK 4096 ; reserve 4096-byte stack
.DATA ; reserve storage for data
number1 BYTE 100 DUP(?);
string1 BYTE "Please input the nuber",cr,Lf,0;
string2 BYTE "ABS is",cr,Lf,0;
.CODE ; start of main program code
_start:
output string1;
input number1,100;
atoi number1;
cmp ax,0;
jle body;
jmp endbody;
body:
neg ax;
endbody:
output string2;
itoa number1,ax;
output number1;
INVOKE ExitProcess, 0 ; exit with return code 0
PUBLIC _start ; make entry point public
END ; end of source code
- 键盘输入一个分数判断其属于哪个等级并显示在屏幕上,等级分别为’A’ (80-100),’B’(60-80),’C’(0-59)。例如输入 85,显示结果A在屏幕上。
;Program:算成绩等级
;Author:龙文汉
;Date:2020.11
.386
.MODEL FLAT
ExitProcess PROTO NEAR32 stdcall, dwExitCode:DWORD
INCLUDE io.h ; header file for input/output
cr EQU 0dh ; carriage return character
Lf EQU 0ah ; line feed
.STACK 4096 ; reserve 4096-byte stack
.DATA ; reserve storage for data
core BYTE 10 DUP(?);
string1 BYTE "Please input the core:",cr,Lf,0;
string2 BYTE "The level is ",cr,Lf,0;
level BYTE 10 DUP(?);
.CODE ; start of main program code
_start:
output string1;
input core,10;
atoi core;
cmp ax,59;
jle level_c;
cmp ax,80;
jle level_b;
mov level,"A";
jmp endbody;
level_c:
mov level,"C";
jmp endbody;
level_b:
mov level,"B";
jmp endbody;
endbody:
output level;
INVOKE ExitProcess, 0 ; exit with return code 0
PUBLIC _start ; make entry point public
END ; end of source code
- 求1+2+3+…+99+100的值,并显示结果在屏幕上。
;Program:循环求值
;Author:龙文汉
;Date:2020.11
.386
.MODEL FLAT
ExitProcess PROTO NEAR32 stdcall, dwExitCode:DWORD
INCLUDE io.h ; header file for input/output
cr EQU 0dh ; carriage return character
Lf EQU 0ah ; line feed
.STACK 4096 ; reserve 4096-byte stack
.DATA ; reserve storage for data
num BYTE 100 DUP(?);
string1 BYTE "The answer is:",cr,Lf,0;
.CODE ; start of main program code
_start:
mov ax,1;
mov bx,0;
whilesum:
cmp ax,100;
jle body;
jmp endbody;
body:
add bx,ax;
inc ax;
jmp whilesum;
endbody:
output string1;
itoa num,bx;
output num;
INVOKE ExitProcess, 0 ; exit with return code 0
PUBLIC _start ; make entry point public
END ; end of source code
- 附加题:题目:计算给定数字的平方、立方值
实验要求:从键盘输入0至9中任一自然数x,求其立方值。若输入的字符不是0至9之间的数字,则显示错误信息,并要求重新输入。要求有信息提示输入数字、显示计算结果和提示输入错误。
提示:用户输入字符首先判断是否是0至9之间的字符,如果是,则转换为整数并计算其立方值,然后显示结果;如果不是,则显示输入错误信息并等待用户重新输入。
例如输入数字为 4,则显示
数值 平方 立方
1 1 1
2 4 8
3 9 27
4 16 64
;Program:
;Author:
;Date:
.386
.MODEL FLAT
ExitProcess PROTO NEAR32 stdcall, dwExitCode:DWORD
INCLUDE io.h ; header file for input/output
cr EQU 0dh ; carriage return character
Lf EQU 0ah ; line feed
.STACK 4096 ; reserve 4096-byte stack
.DATA ; reserve storage for data
string1 BYTE "Please input the number(0-9):",cr,Lf,0;
string2 BYTE "The number is false,please input the correct number(0-9):",cr,Lf,0;
string3 BYTE "squera",cr,Lf,0;
string4 BYTE cr,Lf,"cube:",cr,Lf,0;
cube BYTE 100 DUP(?),cr,Lf,0;
squera BYTE 100 DUP(?),cr,Lf,0;
number BYTE 100 DUP(?),cr,Lf,0;
answer BYTE 100 DUP(?),cr,Lf,0;
.CODE ; start of main program code
_start:
body:
output string1;
input number,100;
atoi number;
cmp ax,0;
jl falsebody;
cmp ax,9;
jg falsebody;
jmp mainbody;
falsebody:
output string2;
jmp body;
mainbody:
output string3;
mov cx,ax;
mul ax;
itoa answer,dx;
output answer;
itoa answer,ax;
output answer;
output string4;
mov ax,cx;
mul ax;
mul cx;
itoa answer,dx;
output answer;
itoa answer,ax;
output answer;
INVOKE ExitProcess, 0 ; exit with return code 0
PUBLIC _start ; make entry point public
END ; end of source code
待更新…