首页 > 代码库 > 汇编第三日

汇编第三日

在.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!!!                 

汇编第三日