• 汇编语言关于程序的模块化编写


    模块化程序设计

    mul乘法指令

    • 要么都是8位,要么都是16位
    • 8位:一个数放在AL中,另一个数放在8位reg寄存器或内存单元中
    • 16位:一个数放在AX中,另一个数放在16位reg寄存器或内存单元中
    • 结果:8位乘法:放在AX中;16位乘法:低位放在AX中,高位放在DX中

    8位乘8位:

    assume cs:code
    code segment
    start:  mov al,100
            mov bl,10
            mul bl 
    code ends
    end start
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    100和10 都是8位(小于256),所以一个数放在al中,另一个数放在另一个8位reg寄存器中,结果放在ax中。 执行结果:ax=03e8h

    16位乘16位:

    assume cs:code
    code segment
    start:  mov ax,100
            mov bx,10000
            mul bl 
    code ends
    end start
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    由于bx为16位,所以另一个数一定为16位,16位对16位,ax存放一个树,16位reg寄存器存放另一个数。结果结果:ax=4240(低16位) dx=0001(高16位)

    模块化程序设计

    三个示例来解决模块化程序设计需要注意的三个问题

    参数传递的问题

    示例:使用子程序的思想,计算N的3次方

    可以使用mul指令,进行三次ax与reg寄存器相乘。将结果存放在dx或ax中

    ; 计算N的3次方
    assume cs:code
    data segment
        dw 1,2,3,4,5,6,7,8  ;存放原始数据
        dd 0,0,0,0,0,0,0,0  ;存放相乘结果
    data ends
    code segment
    start:  mov ax,data
            mov ds,ax
            mov di,0        ;原始数据的起始地址
            mov si,16       ;结果存储的起始地址
    
            mov cx,8
        s:  mov bx,[di] 
            call go
            
            ;返回到这里
            mov [si],ax     ;ax存放低16位
            mov [si+2],dx   ;dx存放高16位
            add di,2        ;数据移动
            add si,4        ;目标位置移动
            loop s  
    
            ;结束程序
            mov ax,4c00h
            int 21h
    
        go: mov ax,bx       
            mul bx
            mul bx
            ret             ;返回主程序
    code ends
    end start
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    分别计算每一个数字的3次方,将结果存储到dd的双字型内存单元中,从主程序传递ds数据到子程序,计算后返回结果送到目的地,同时注意原始数据和目标数据的偏移地址的移动

    批量数据传递

    示例:将一个字符串全部转换为大写

    批量的将字符串长度和地址传递给子程序,进行转换后再回到主程序

    提示:

    • 将小写字母转换为大写字母: 与运算: and al,11011111B
    • 将大写字母转换为小写字母: 或运算: or al,00100000B
    ;转大写
    assume cs:code
    data segment 
        db 'woshixiaoxiehhhh'
    data ends
    code segment
    start:  mov ax,data
            mov ds,ax
            mov bx,0
    
            mov si,0        ;字符串的偏移地址
            mov cx,16       ;字符串长度
            call go
    
            ;程序结束
            mov ax,4c00h
            int 21h
    
        go: and byte ptr [si],11011111B     ;指明接受的是byte型字节数据
            inc si          ;偏移地址移动定位每个字符
            loop go         ;循环处理每个字符
            ret             ;返回主程序
    code ends
    end s
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    传递给子程序长度,即cx,来在子程序中对每个字母进行与运算,处理完毕后在统一回到主程序

    寄存器冲突问题

    示例:将多个字符串转换为大写

    和上一题基本一致,但是要处理多行,用一个si或者di记录位置,这样能解决吗?

    提示:没必要传给子程序cx来记录字符串的长度,直接用jcxz(如果cx为0,则执行跳转)来检测结束

    ;jcxz检测零实现
    assume cs:code
    data segment 
        db 'woshixiaoxie',0,0,0,0
        db 'woshixiaoxie',0,0,0,0
        db 'woshixiaoxie',0,0,0,0
        db 'woshixiaoxie',0,0,0,0
        db 'woshixiaoxie',0,0,0,0
    data ends
    code segment
    start:  mov ax,data
            mov ds,ax
    
            mov bx,0
            mov cx,5
    s1:     mov si,bx        ;字符串的偏移地址
            push cx          ;临时保存主程序CX
    
            call go
    
            ;CX出栈,保持主程序和子程序的cx不一样
            pop cx           ;临时保存cx
            add bx,16        ;换行
            loop s1          ;循环
    
            mov ax,4c00h
            int 21h
            
    go:     mov cl,[si]
            mov ch,0             ;判断cx是否为零
            jcxz over            ;使用jcxz则无需直到字符串的长度,只要cx为零,则终止
            and byte ptr [si],11011111B
            inc si               ;偏移地址移动定位每个字符
            loop go              ;循环处理每个字符
    
    over:   ret                  ;返回主程序
    code ends
    end start
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    注意:此题用jcxz over表示遇到零则结束,在子程序中将按照ds数据段的数据来判断CX,进而判断字符除按是否到达末尾,最后利用jcxz返回主程序。注意!!!!!!
    在返回主程序后!!子程序的cx也会返回,进而覆盖了主程序的cx(原本外层的cx用来换行每一个字符串),因此需要利用在进入子程序之前或者进入子程序马上push cx来保存外层的cx,在结束到over或者处理结束进入主程序之后再pop cx得到原来外层的cx,进而进行下一行字符串的处理

  • 相关阅读:
    【postgresql 基础入门】带过滤条件的查询,where子句中的操作符介绍,案例展示,索引失效的大坑就在这里
    2023年09月 Python(一级)真题解析#中国电子学会#全国青少年软件编程等级考试
    GoFrame Goland插件
    类与对象练习一
    mkv视频格式转换mp4格式
    LeetCode刷题:88. 合并两个有序数组
    Remix v2 中使用 remix-i18n 进行国际化翻译
    中英文说明书丨CalBioreagents艾美捷甲型流感病毒单克隆抗体
    火焰图:链路追踪分析的可视化利器
    深度学习遇到 DolphinDB AI DataLoader
  • 原文地址:https://blog.csdn.net/jj6666djdbbd/article/details/126800757