首页 > 代码库 > 汇编第三日
汇编第三日
在.asm文件中写mov al, [0],对于编译器来说只是将0赋值给al(不过写[0]相当于写ds:[0],写[1],[2]....这些就不相同了)
为了表示我们想要的ds:[0]:
1.改写成mov al, ds:[0]
2.
mov bx, 0
mov al, [bx]
所以bx寄存器基本上与内存地址挂钩
cx寄存器基本上记录loop循环次数,也可记录源代码行数
loop基本语法:
mov cx, 11
标号:循环体
loop 标号 ;这三条语句尽量靠近,防止其他语句对寄存器值进行修改
loop执行过程:
(cx) = (cx) - 1 //寄存器外加个"( )"表示寄存器的内容,为了更好表示寄存器
若(cx)不为0,跳转到标号执行;若为0,执行loop下一条语句
编写汇编代码时,若想表示16进制数据,在数据后加上‘H‘ 或 ‘h’,并且数据不能以字母开头,例如FFFFH只能写成0FFFFH.
add ax, ax :表示幂的计算
add ax, data :表示乘法的计算
对于8位数据与16位寄存器数据相加,结果放在寄存器中:
首先8位数据无法直接使用 add 来与16位数据相加,所以8位数据先放到充当中介作用的寄存器的低8位,高8位置0,之后和16位寄存器相加即可
实现局部代码:
mov bx, 0 mov cx, 12 s: mov al, [bx] mov ah, 0 add dx, ax inc dx loop s
inc:(bx) = (bx) + 2
;封号作为注释
段前缀概念:
mov ax,cs:[0]/ds:[0](ds和cs即为段前缀)
一般PC中,0:200 --- 0:2FF为安全空间即不干扰OS运行
可以情况下,ds:[...]化一下更为简单,例如 200:100 - 200:1FF 可以化成 210:0 - 210:FF等等
dw指令和db指令:
dw:define word 定义字型数据
db:define byte 定义字节数据
dw语法:
dw 0102H,0304H,0506H
0102H占了一个字(两个内存存储空间)
一旦出现dw和或db,那么定义标号就很有必要。之前没有定义dw或db时,没有定义标号是不影响程序执行和结果,虽然报个warning:没有程序入口地址;但是定义了dw或db时,若没有标号,那么当汇编指令转化成机器指令时,CPU会认为用户定义的数据也为指令,从而执行出错。所以要注明标号指明程序入口地址。
但是有个特殊点:当我们把指令写为第一个段,db或dw定义在其后的话,CPU还是从第一段指令开始执行,直到end结束执行,结果依然正确
汇编指令结尾end作用:
1.通知编译器程序结束
2.得到程序入口地址(真正执行机器指令时,CPU会先去找end,从而根据其后的标号找到程序入口地址)
若数据或指令需要大于64KB(8086:一个段最大容量)时,需要多个段空间来执行,主要是封装的思想,毕竟64KB比较大,而之后的i386的32位对应最大段容量为4GB
实例:
assume cs:code,ds:data,ss:stack //将地址与相应的寄存器挂钩 data segment dw 0123h,0456h data ends stack segment dw 0,0 stack ends code segment start: mov ax,stack mov ss,ax //也无法给ss mov sp,16 mov ax,data //同理标号data为数据无法直接给ds mov ds,ax push ds:[0] push ds:[2] pop ds:[2] pop ds:[0] mov ax,4c00h int 21h code ends end start
ES为附加段寄存器
当可执行文件加载进内存时,CS:IP会被设置成end 标号对应的程序入口地址,从而开始执行第一条指令
CPU靠CS:IP,SS:SP,DS:[...]来认识代码段,栈,数据段
Done!!!
汇编第三日