8086 asm文件语法-2

Posted 不会写代码的丝丽

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了8086 asm文件语法-2相关的知识,希望对你有一定的参考价值。

无条件跳转

jmp short 标号

段内跳,仅能跳转单个字节长度范围(255)

data_seg segment
    g_szSrc db "abcde$"
    g_szDst db 255 dup(0cch)
data_seg ends

code segment
START:
    assume ds:data_seg
    mov ax,data_seg
    ;放入ds到正确位置
    mov ds,ax
    ;不加 short 也是可以的
    jmp short LABLE1
    mov ax,ax
LABLE1:
    mov bx,bx
    ;不加near ptr 也是可以的 但是不能写 short否则编译报错
    jmp  LABLE2
    db 256 dup(01h)   
    mov bx,bx
LABLE2:
    mov bx,bx
code ends

end START

上面代码我们运行下:

执行到跳转前

执行跳转后

我们来编译一个错误的示例:

data_seg segment
    g_szSrc db "abcde$"
    g_szDst db 255 dup(0cch)
data_seg ends

code segment
START:

    mov bx,bx
    ;强制声明为单字节跳转但是lable2的地址超过255因此会报错
    jmp  short LABLE2
    db 256 dup(01h)   
    mov bx,bx
LABLE2:
    mov bx,bx
code ends

end START

jmp near ptr 标签

段内跳,仅能跳转2个字节长度范围(65535)

参考jmp short

jmp far ptr 标签

可以跨段跳,会修改cs和ip数值

data_seg segment
    g_szSrc db "abcde$"
    g_szDst db 255 dup(0cch)
data_seg ends

code_seg2 segment
LABLE:
    mov si,si
code_seg2 ends

code segment
START:
    assume ds:data_seg
    mov ax,data_seg
    mov bx,code_seg2
    jmp far ptr LABLE
code ends

end START



通过寄存器跳转

code segment
START:
   assume ds:data_seg

   lea ax,LABLE2
   jmp ax
LABLE2:
   mov ax,ax
code ends

end START

通过EA跳转

段内

从内存中取出2字节进行跳转

  1. jmp 变量名字
  2. jmp word ptr [EA]
  3. jmp near ptr [EA]
data_seg segment
    g_szDst dw 0
data_seg ends



code segment
START:
    assume ds:data_seg
    mov ax,data_seg
    mov ds,ax
    lea ax,LABLE2
    assume ds:data_seg
    mov g_szDst,ax
    jmp g_szDst
    jmp word ptr g_szDst
    ;下列语句不支持 可以改用另一种比较迂回的方式
    ; jmp near ptr g_szDst
    lea bx,g_szDst
    jmp near ptr [bx]

    
    
LABLE2:
    mov ax,ax
code ends

end START

跨段

从内存中分别取两个字节分别用与修改cs和ip从而完成跨段跳转.前一个字放入ip,后一个字放入cs

  1. jmp 变量名
  2. jmp dword ptr [EA]
  3. jmp far ptr [EA]
data_seg segment
    ;定义一个双字,注意必须定义双字否则编译器可能视为段内跳转
    g_szDst dd 0
data_seg ends


jmp_seg segment
LABLE2:
    mov bx,ax
jmp_seg ends



code segment
START:
    assume ds:data_seg
    mov ax,data_seg
    mov ds,ax
    
    lea bx,g_szDst
    ;第一个字放入到ip所以此处放入段内偏移
    mov word ptr [bx],offset LABLE2
    ;后移动一个字放入段地址
    add bx,2
    ;后一个字作为段地址
    mov word ptr[bx],jmp_seg
    
    jmp g_szDst
    jmp dword ptr[bx]
    jmp far ptr [bx]

code ends

end START

条件跳转

首先我们大致浏览如下表格

举例其中一个用法即可

data_seg segment
    ;定义一个双字,注意必须定义双字否则编译器可能视为段内跳转
    g_szDst dd 0
data_seg ends


code segment
START:
    assume ds:data_seg
    mov ax,data_seg
    mov ds,ax
    ;让zf标志为1
    ; xor ax,ax
    jz LABLE1
    mov bx,bx
LABLE1:
    mov ax,ax

code ends

end START

循环

指令重复条件
LOOPCX!=0
LOOPZ/LOOPEcx!=0 且 zf ==1
LOOPNZ/LOOPNEcx!=0 且 zf ==0

下面我们输出hello world$到屏幕

data_seg segment
    ;定义一个双字,注意必须定义双字否则编译器可能视为段内跳转
    g_szDst db "hello world$"
    g_bLen db 0
data_seg ends


code segment
START:
    assume ds:data_seg
    mov ax,data_seg
    mov ds,ax
    ;设置标志寄存器,目的让lodsb执行后自动si+1
    CLD
    lea si,g_szDst
    ;设置cx长度为字符串长度
    mov cx,offset g_bLen- offset g_szDst
   
 LOOP_START:
    lodsb ;去除一个字符放入al
    ;调用系统函数此处为输出字符到屏幕
    mov dl,al
    mov ah,2
    int 21h
    ;自动让cx减一,当cx==0时停止循环 
    loop LOOP_START

LABLE1:
    mov ax,ax

code ends

end START

一个更复杂的例子,改造上面的例子当我们输出字符到o的时候自动停止输出

data_seg segment
    ;定义一个双字,注意必须定义双字否则编译器可能视为段内跳转
    g_szDst db "hello world$"
    g_bLen db 0
data_seg ends


code segment
START:
    assume ds:data_seg
    mov ax,data_seg
    mov ds,ax
    ;设置标志寄存器,目的让lodsb执行后自动si+1
    CLD
    lea si,g_szDst
    mov cx,offset g_bLen- offset g_szDst
   
 LOOP_START:
    lodsb ;去除一个字符放入al
    ;调用系统函数
    mov dl,al
    mov ah,2
    int 21h
    ;与o做比较然后影响标志位
    cmp al,'o'
    ;自动让cx减一,当cx!=0且zf!=0继续循环 
    loopnz LOOP_START

    ;停止输出
    mov ax,4c00h
    int 21h

LABLE1:
    mov ax,ax

code ends

end START

以上是关于8086 asm文件语法-2的主要内容,如果未能解决你的问题,请参考以下文章

8086 asm文件语法-1

8086 asm文件语法-1

在 DOSBox 中运行 ml program.asm 时 8086 程序没有输出

8086汇编 程序编译

没有 div 的 ASM 8086 除法

8086asm中的struc类型数据无法打印