x86 masm 通用的代码记录

编写环境:vscode+DOSBox 0.7.4+masm

vscode插件:VSCode DOSBox

1. 在屏幕显示字符串

应用举例:在屏幕的8行3列,用绿色显示data段中的字符串

;名称:showstr
;功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串。
;参数:(dh)=行号(取值范围0~24),(dl)=列号(取值范围 0~79),(cl)-颜色,ds:si指向字符串的首地址
;返回:无
showstr:
    push ax
    push cx
    push dx
    push es
    push si
    push di
    mov ax,0B800H ;32kb 的显存
    mov es,ax
    
    ;计算位置  25行 80列
    ; dh*160+dl*2
    dec dh
    mov al,160
    mul dh
    add dl,dl
    mov dh,0
    add ax,dx
    mov di,ax

    ;ax: ah al ; al 存字符,ah存颜色
    mov ah,cl ;ah存颜色
    mov si,0
set_char:
    mov cl,ds:[si]
    mov ch,0
    jcxz showstr_done
    mov al,cl  ;al 存字符
    mov es:[di],ax
    inc si
    add di,2
    jmp set_char

showstr_done:
    pop di
    pop si
    pop es
    pop dx
    pop cx
    pop ax
    ret

2.解决除法溢出问题

​ 应用举例:计算1000000/10(F4240H/0AH)

; 名称:divdw
;    功能:进行不会产生溢出的除法运算,被除数为 dword 型,除数为 word 型,结果为dword 型。
;    参数:(ax)=dword型数据的低 16位
;          (dx)=dword型数据的高16位
;          (cx)=除数
;    返回:(dx)=结果的高16 位,(ax)=结果的低 16位
;          (cx)=余数
divdw:
    push bx

    push ax
    mov ax,dx
    mov dx,0
    div cx      ;1.先算高位的余数和商,结果放到dx和ax中
    mov bx,ax   ;将高位结果商(ax)放到bx中,后续放到dx中
    pop ax      ;2.再算低位的余数和商
    div cx      ;dx是高位的余数,和低位ax中进行除法运算
    mov cx,dx   ;dx中是低位的余数,按题目要求放到cx中
    mov dx,bx   ;
    
    pop bx
    ret

3.word 数值显示问题

编程,将data段中的数据以十进制的形式显示出来。

;名称:dtoc
;功能:将word型数据转变为表示十进制数的字符串,字符串以0为结尾符。
;参数:(ax)=word型数据
;       ds:si指向字符串的首地址
;返回:无
dtoc_word:
    push ax
    push bx
    push cx
    push dx
    push si

    mov bx,0
div_loop:
    mov dx,0
    mov cx,10
    div cx  ;dx位商,ax为余数

    add dx,'0'
    push dx
    inc bx

    mov cx,ax
    jcxz div_loop_out
    jmp div_loop

div_loop_out:
    mov cx,bx

    mov si,0
set_data:
    pop ds:[si]
    inc si
    loop set_data
    pop si
    pop dx
    pop cx
    pop bx
    pop ax
    ret

4 dword 数值显示代码

;名称:dtoc_dword
;功能:将dword 型数转变为表示十进制数的字符串,字符串以0为结尾符。
;参数:(ax)=dword型数据的低16位
;     (dx)=dword型数据的高16位
;      ds:si指向字符串的首地址
;返回:无
dtoc_dword:
    push ax
    push bx
    push cx
    push dx
    push si

    mov bx,0
dtoc_dword_div:
    mov cx,10
    call divdw
    push cx
    inc bx
    cmp ax,0
    jne dtoc_dword_div
    cmp dx,0
    jne dtoc_dword_div

    mov si,0
    mov cx,bx
dtoc_dword_set_data:
    pop ds:[si]
    add byte ptr ds:[si],'0'
    inc si
    loop dtoc_dword_set_data

    pop si
    pop dx
    pop cx
    pop bx
    pop ax
    ret

5.清除当前页面数据

;清空屏幕
clear_screen:
    push ax
    push cx
    push es
    push di

    mov ax,0b800h
    mov es,ax	 ;(es)=(0b800h)
    mov cx,80*25	;清屏总共需要写 80*25 个字符
    mov di,0	;初始化偏移地址为 0
clear_screen_loop:	;清屏
    mov byte ptr es:[di],' '	;将空格写入显存
    mov byte ptr es:[di+1],0	;将颜色属性写入显存
    add di,2	;偏移地址加 2
    loop clear_screen_loop	;循环清屏

    pop di
    pop es
    pop cx
    pop ax
    ret

6.字符串转大写

将包含任意字符,以0结尾的字符串中的小写字母转变成大写字母

data segment
    db "Beginner's All-purpose Symbolic Instruction Code.",0
data ends
;名称:letterc
;功能:将以0结尾的字符串中的小写字母转变成大写字母
;参数:ds:si指向字符串首地址
letterc:
    push si
    push ax
letterc_label:
    mov al,[si]
    cmp al,0
    je letterc_ok
    inc si
    cmp al,'a'
    jb letterc_label
    cmp al,'z'
    ja letterc_label
    add al,'A'-'a'
    mov ds:[si-1],al
    jmp letterc_label

letterc_ok:
    pop ax
    pop si
    ret
posted @ 2025-09-25 11:27  长江~之星  阅读(13)  评论(0)    收藏  举报