汇编语言基于8086CUP(想学操作系统的前奏!!!)
阅读原文时间:2023年07月08日阅读:1

汇编语言基于8086CUP(想学操作系统的前奏!!!)

1.1、思维图

1.2、单位转换

1B=8bit

1KB=1024B

1MB=1024KB

1GB=1024MB

1TB=1024GB

1字=2字节=2B=16位

1.3、储存器与内存

因为在这些总线上传输的都是2进制的数,所以可能传输的是相同的2进制数,需要区分哪些是数据,哪些又是指令,所以需要通过不同的总线就行传输来控制。

地址总线:20位2进制

数据总线:16位2进制

控制总线:16位2进制

2.1、14个寄存器

AX,BX,CX,DX,SI,DI,SP,BP,IP,CS,SS,DS,ES,PSW;

几位寄存器,表示可以存储几位二进制数

AX,BX,CX,DX一般被称为通用寄存器,

AX可以分为AH和AL

BX可以分为BH和BL

CX可以分为CH和CL

DX可以分为DH和DL

2.2、地址总线

由于8086有20位的地址总线,所有在传输16位时需要地址加法器进行处理变成20位

地址加法器:物理地址=段地址*16+偏移地址

传送地址时需要传送两个16位的地址,一个称为段地址,一个称为偏移地址

段寄存器:CS,DS,SS,ES

CS:为代码段寄存器

IP:指令指针寄存器

2.3、DS和[address]

这样的指令 mov ax,[0] (调试的时候可以这么写,写.asm源文件时需要写成 mov bx,0,mov ax,[bx];需要bx中间量来转换一下) 把默认段地址+偏移地址的第一位取出来放到ax上

DS存放的是默认的段地址

2.4、栈(Last in frist out)后进先出

push(入栈)

pop(出栈)

段寄存器SS:存放栈顶的段地址

寄存器SP:存放栈顶的偏移地址

SS:SP表示栈顶元素

2.5、SI和DI

SI和DI,也用来表示偏移地址,使用[bx]时不够用,所以可以使用[SI],[DI]

2.6、栈解决多层循环问题

2.7、寻址方式

寻址方式

含义

名称

常用格式举例

[idata]

EA=idata;SA=(ds)

之间寻址

[idata]

[bx]
[si]
[di]
[bp]

EA=(bx);SA=(ds)
EA=(si);SA=(ds)
EA=(di);SA=(ds)
EA=(bp);SA=(ss)

寄存器间接寻址

[bx]

[bx+idata]
[si+idata]
[di+idata]
[bp+idata]

EA=(bx)+idata;SA=(ds)
EA=(si)+idata;SA=(ds)
EA=(di)+idata;SA=(ds)
EA=(bp)+idata;SA=(ss)

寄存器相对寻址

用于结构体[bx].idata
用于数组,idata[si]<br/

[bx+si]
[bx+di]
[bp+si]
[bp+di]

EA=(bx)+(si);SA=(ds)
EA=(bx)+(di);SA=(ds)
EA=(bp)+(si);SA=(ss)
EA=(bp)+(di);SA=(ss)

基址变址寻址

用于二维数组,[[bx][si]][si]

[bx+si+idata]
[bx+di+idata]
[bp+si+idata]
[bp+di+idata]

EA=(bx)+(si)+idata;SA=(ds)
EA=(bx)+(di)+idata;SA=(ds)
EA=(bp)+(si)+idata;SA=(ss)
EA=(bp)+(di)+idata;SA=(ss)

相对基址变址寻址

用于表格
二维数组

2.8、标志位

标志位

作用

ZF

如果执行的结果为0,ZF=1,反之

PF

如果执行的结果中有偶数个1,则PF=1,反之

SF

如果执行的结果中最高位为1,则SF=1,反之

CF

如果计算出现进位或者借位,加法进位,减法借位,会在CF中标志1

OF

如果无符号计算,出现位不够用,出现溢出,会在OF中标出1

DF

DF决定串传送指令后,si和di方向的改变,DF=0,+;DF=1,-

TF

RF位为1,就产生单步中断,也就是指令t

无符号数:cmp ax,bx

  1. 如果(ax)=(bx),则(ax)-(bx)=0,所以:ZF=1
  2. 如果(ax)!=(bx),则(ax)-(bx)!=0,所以:ZF=0
  3. 如果(ax)<(bx),则(ax)-(bx)将产生借位,所以:CF=1
  4. 如果(ax)>=(bx),则(ax)-(bx)将不借位,所以:CF=0
  5. 如果(ax)>(bx),则(ax)-(bx)不借位且结果不为0,所以:CF=0,且ZF=0
  6. 如果(ax)<=(bx),则(ax)-(bx)可能借位,可能为0,所以:CF=1或者ZF=1

有符号数:cmp ah,bh

  1. 如果(ah)<(bh),则(ah)-(bh)最高位会为1,如果不溢出,则SF=1,OF=0
  2. 如果(ah)>(bh),则(ah)-(bh)最高位会为1,如果溢出,则SF=1,OF=1
  3. 如果(ah)<(bh),则(ah)-(bh)最高位会为0,如果溢出,则SF=0,OF=1
  4. 如果(ah)>=(bh),则(ah)-(bh)最高位会为0,如果不溢出,则SF=0,OF=0

3.1、汇编指令的用法

汇编指令

语法描述

mov ax,18

ax=18

add ax,18

ax=ax+18

sub ax,18

ax=ax-18

inc ax

ax=ax+1

dec ax

ax=ax-1

jmp 段地址:偏移地址

修改CS和IP的内容(在汇编指令使用,编译器不认识)

push ax

把ax入栈

pop ax

把栈顶元素出栈保存到ax中

loop S:需要循环的指令段 loop S

控制循环的指令,具体循环多少次,由CX中的数决定

dw dw 0123H,1234H,0024H

定义数据存放在内存中,占两个字节

db db 0,1,2,4,5,6,7,8

定义数据存放在内存中,占一个字节

and and al,11011111b

与运算,把al的第五位二进制转化为0

or or al,00100000b

或运算,把al的第五位二进制转化为1

div div bx

除法运算,{(dx)*10000H+(ax)}/(bx)

mul mul bx

乘法运算,(dx)10000H+(ax)=(ax)(bx),都是8位就存放在ax中

dd

定义数据存放在内存中,占四个字节,2个字,32位

dup db 200 dup(0)
db 2 dup('ab','AB')

定义了200个连续为0的字节
定义了"adABabAb"的8个字节的数据

jmp short s

段内转移,指令跳转到标号s处,位移为8位

jmp near ptr s

段内转移,指令跳转到标号s处,位移为16位

jmp far ptr s

段间转移,指令跳转到标号s处,改变CS:IP为s处的CS,IP

jmp ax

指令跳转到ax存放的值当作ip去转移

jmp word ptr 内存地址

段内转移,存放的一个字,表示跳转的偏移地址IP

jmp dword ptr 内存单元地址

段间转移,存放的两个字,表示跳转(CS)=(内存+2),(IP)=(内存)

jcxz s

条件段内转移,如果(cx)=0跳转到s处,否则不跳转

mov ax,offset s

取得s处的偏移地址,把值赋给ax

ret

表示把栈顶的元素值给了IP,改变程序执行的位置

retf

表示把栈顶的元素值给了IP,第二个值给 CS

call s

把当前IP入栈,在跳转(位移16位来实现的)到s处,

call far ptr s

把CS入栈、把IP入栈,把s处的段地址给CS、偏移地址给IP

call ax

把当前IP入栈,把通用寄存器ax的值给IP

call word ptr 内存单元地址

把当前IP入栈,IP该我内单元地址2字节

call dword ptr 内存单元地址

把当前CS入栈、IP入s栈,把高位2字节给CS、低位2字节給IP

abc abc ax,bx

带进位加法指令,(ax)=(ax)+(bx)+CF

sbb sbb ax,bx

带进位减法指令,(ax)=(ax)-(bx)-CF

cmp cmp ax,bx

结果不会保存在任何位置,但会影响标志位的变化

je s

等于则转移到 s标志位,ZF=1,equal:等于

jne s

不等于则转移 s标志位,ZF=0,

jb s

低于转移到 s标志位,CF=1,below:小于

jnb s

不低于转移到 s标志位,CF=0

ja s

高于转移到 s标志,CF=0,ZF=0,above:大于

jna s

不高于则转移到 s标志位,CF=1,或者ZF=1

movsb

将ds:si中的值送入es:si中:((es)16+(di))=((ds)16+(si)}),
如果DF=0,则(si)=(si)+1,(di)=(di)+1;
如果DF=1,(si)=(si)-1,(di)=(di)-1

movsw

以字的单元传送,规则同movsb

rep movsb

根据cx的值来重复传送cx次,实现传送字符串的作用

cld

将标志寄存器DF=0

std

将标志寄存器DF=1

pushf

将标志寄存器的值压栈

popf

弹栈出到标志寄存器中

iret

在中断程序执行,IP,CS,标志寄存器的弹栈

shl

向左移动一位,右边补零,移出的一位保存道CF中

shr

向右移动一位,左边补零,移出的一位保存道CF中

cli

将标志寄存器IF=0,不处理外中断

sti

将标志寄存器IF=1,处理外中断

3.2、Windows11下载Dosbox来使用debug命令窗口

第一步去官网下载:Dosbox;[官网 ][ https://www.dosbox.com/download.php?main=1 ]

第二步修改你需要在哪个盘哪个文件中操作:

masm文件

asm文件

最后打开DOSbox.exe就可以操作了

Debug指令

R命令,查看、改变CPU寄存器的内容

D命令,查看内存中的内容

E命令,改变内存中的内容

A命令,可以在段地址CS,偏移地址IP写入一条机器指令

T命令,执行一条机器指令

U命令,将内存中的机器指令翻译成汇编指令

  1. 计算2的三次方

    assume cs:abc
    
    abc segment
        mov ax,2
        add ax,ax
        add ax,ax
    mov ax,4c00H
    int 21H
    abc ends end
  2. 操作内存地址,改变值

    assume cs:abc
    
    abc segment
    
    start:    mov ax,2000H
            mov ds,ax
            mov bx,1000H
            mov ax,[bx]
            inc bx
            inc bx
            mov [bx],ax
            inc bx
            inc bx
            mov [bx],ax
            inc bx
            mov [bx],al
            inc bx
            mov [bx],al
        mov ax,4c00H
        int 21H
    abc ends end start
  3. 计算2的11次,用loop循环执行

    assume cs:abc
    
    abc segment
    
    start:    mov ax,2
            mov cx,11
        S:  add ax,ax
            loop s
        mov ax,4c00H
        int 21H
    abc ends end start
  4. 循环操作4个单位内存中数据之和

    assume cs:abc
    
    abc segment
    
    start:
            mov ax,1000H
            mov ds,ax
        mov bx,0000H
        mov al,0011H
        mov ds:[bx],al      
    
        mov bx,0001H
        mov al,0022H
        mov ds:[bx],al      
    
        mov bx,0002H
        mov al,0033H
        mov ds:[bx],al      
    
        mov bx,0003H
        mov al,0044H
        mov ds:[bx],al
    
        mov ax,0000H
        mov cx,0004H
        mov bx,0004H
        mov dx,0000H
    S:  sub bx,cx
        mov al,[bx]
        add dx,ax
        mov bx,0004H
        loop S
    
        mov ax,4c00H
        int 21H
    abc ends end start
  5. 利用栈交换顺序

    assume cs:abc
    
    abc segment
        dw 0123H,1234H,0252H,12A2H,2222H,3333H,4444H,5555H
        dw 0,0,0,0,0,0,0,0
    
    start:
            mov ax,cs
            mov ss,ax
            mov sp,32
            mov bx,0
            mov cx,8
        S:
            push cs:[bx]
            add bx,2
            loop S
        mov bx,0
        mov cx,8
    S1:
        pop cs:[bx]
        add bx,2
        loop S1
    
        mov ax,4c00H
        int 21H
    abc ends end start
  6. 计算a,b两个段数据依次相加的结果存放到c段中

    assume cs:abc,ds:a
    
    a segment
        db 1,2,3,4,5,6,7,8
    a ends
    
    b segment
        db 1,2,3,4,5,6,7,8
    b ends
    
    c segment
        db 0,0,0,0,0,0,0,0
    c ends
    
    abc segment
    start:
            mov ax,a
            mov ds,ax
            mov dx,0000H
            mov cx,8
    S:  mov bx,dx
        mov ah,ds:[bx]
        add bx,16
        mov al,ds:[bx]
        add ah,al
        add bx,16
        mov ds:[bx],ah
        add dx,1
        loop S
    
        mov ax,4c00H
        int 21H
    abc ends end start
  7. 将小写字母转化为大小字母

    assume cs:abc,ds:a
    
    a segment
    db 'BAsiC'
    db 'abcdefgh'
    a ends
    
    abc segment
    start:
            mov ax,a
            mov ds,ax
        mov bx,0
    
        mov cx,5
    S1: mov al,[bx]
        and al,11011111b
        mov [bx],al
    
        inc bx
        loop S1
    
        mov bx,5
    
        mov cx,8
    S2: mov al,[bx]
        and al,11011111b
        mov [bx],al
    
        inc bx
        loop S2
    
        mov ax,4c00H
        int 21H
    abc ends end start
  8. 把每一个小写字母的前四位转化为大写

    assume cs:code,ds:data,ss:stack
    
    data segment
    db '1. abcdef.......'
    db '2. mnijwq.......'
    db '3. iloveyou.....'
    db '4. oklolp.......'
    data ends
    
    stack segment
    dw 0,0,0,0,0,0,0,0
    stack ends
    
    code segment
    start:
            mov ax,data
            mov ds,ax
            mov ax,stack
            mov ss,ax
            mov sp,16
        mov bx,0
        mov cx,4
    S0: push cx
        mov si,0
        mov cx,4
    S1: mov al,[bx+3+si]
        and al,11011111b
        mov [bx+3+si],al
        inc si
        loop S1
    
        add bx,16
        pop cx
        loop S0
    
        mov ax,4c00H
        int 21H
    code ends end start
  9. cmd窗口中间输入不同颜色和背景的字符串

    assume cs:code,ds:data,ss:stack
    
    data segment
        db 'welcome to masm!'
        db 02h,24h,71h
    data ends
    
    stack segment
        dw 8 dup(0)
    stack ends
    
    code segment
    
    start:
            mov ax,data
            mov ds,ax
            mov ax,stack
            mov ss,ax
            mov sp,10h
        xor bx,bx
        mov ax,0b872h
    
        mov cx,3
    s3: push cx
        push ax
        push bx
    
        mov es,ax
    
        mov si,0
        mov di,0
    
        mov cx,10h
    
    s1: mov al,ds:[si]
        mov es:[di],al
        inc si
        add di,2
        loop s1
    
        mov di,1
        pop bx
        mov al,ds:10h[bx]
        inc bx
    
        mov cx,10h
    s2: mov es:[di],al
        add di,2
        loop s2
    
        pop ax
        add ax,0ah
    
        pop cx
        loop s3
    
        mov ax,4c00h
        int 21H
    code ends end start

    结果:

  10. 利用call和ret来实现函数,计算一组数的三次方并保存在内存中

    assume cs:code,ds:data
    
    data segment
        dw 1,2,3,4,5,6,7,8
        dw 0,0,0,0,0,0,0,8
    data ends
    
    code segment
    
    start:
            mov ax,data
            mov ds,ax
        mov cx,8
        mov di,0
    s0: mov bx,ds:[di]
        call s
        mov ds:[di+16],ax
        add di,2
        loop s0
    
        mov ax,4c00h
        int 21H
    
    s:  mov ax,bx
        mul bx
        mul bx
        ret
    code ends end start