提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
一.显示字符串
;第一行的起始位置是 B8000h, 第二行的起始位置B8a00h
;显存的起始位置是B8000h
;在我执行2.exe后空格向下(enter)会刷新一行显存页面,所以要想在执行2.exe后,在第一行显示内容.起始地址应该使用B80a0h,
;因为第一行总会乘上1.除非乘以0(结果会被enter,刷新掉), 所以起始位置使用B80ah
;该程序可以把以0结尾的字符串,输入到屏幕指定的行和列
assume cs:code
data segment
db'Welcome to SKSK!', 0
data ends
stack segment
dw 16 dup(0)
stack ends
code segment
start: mov dh, 8 ;行号, 输入行号
mov dl, 3 ;列号, 输入列号
mov cl, 2 ;颜色-绿色
mov ax, data
mov ds, ax ;定位数据段
mov di, 0
mov ax, stack ;设置栈段地址
mov ss, ax
mov sp, 32
mov ax, 0B800h ;设置显存目标段
mov es,ax
call show_str ;在屏幕的给点定行列,用给定颜色显示字符串
mov ax, 4c00h
int 21h
show_str: ;这个程序改变了ax, cx, si , di
push ax
push si
push cx
mov al, 0a0h ;计算目标行
mul dh
mov si, ax
mov al, 02h ;计算目标列,列减1,是因为列是从0开始计算的,行不减,因为在执行程序的过程中,会刷新掉第1行,直接显示第2行
sub dl, 01h
mul dl
add si, ax
mov al, cl ;颜色
showBeg1: mov cl, ds:[di] ;在ds处取出数据,写入现存
mov ch, 0
mov es:[si], cl
jcxz showEnd1 ;如果cx = 0,说明遇见了字符串结尾符0, 我们跳出循环
inc di ;准备写出下一个字符
inc si ;递增到刚写入字符,的颜色内存(一个字节)
mov es:[si], al ;写入颜色
inc si ;准备接受下一个字符
jmp short showBeg1 ;无条件跳转
showEnd1: pop cx
pop si
pop ax
ret
code ends
end start
二.解决除法溢出问题
;一个不会溢出的除法运算,被除数dword, 除数word
;结果: dx 高16位, ax 低16位, cx余数
;16位除法, ax存储商,dx存储余数
;16位乘法, dx存放高位,ax存放低位
assume cs:code
stack segment
dw 0,0,0,0,0,0,0,0
stack ends
code segment
start:mov ax, stack
mov ss, ax
mov sp, 10h
mov ax, 4240h
mov dx, 000FH
mov cx, 0AH
call divdw
mov ax, 4c00h
int 21h
divdw:
push ax
mov ax,dx
xor dx,dx; 清0
div cx
pop bx
push ax;存入商,存入L, 这里的余数
push bx
mov ax,dx ;rem(i) * 65535
mov bx,256 ;乘法这里的乘法,要乘以65535,16位的数不能放下65535, 使用了巧妙的方法乘以两次256
mul bx
mul bx
pop bx
add ax,bx ;rem(i) * 65535 + L ? (这里为何在低位加上bx,会进位到,dx吗?也许会
div cx ;(rem(i) * 65535 + L) /N
mov cx,dx ;保存余数, 余数只能由(rem(i) * 65535 + L) /N 产生
pop dx
push ax
mov ax,dx
mov bx,256 ;int(H / N)*65536
mul bx
mul bx
pop bx
add ax,bx ;int(H / N)*65536 + (rem(i) * 65535 + L) /N
ret
code ends
end start
3. 数值显示
ASSUME cs:code, ds:data, ss:stack
data segment
dw 123, 12666, 11, 12, 2002, 1
db 32 dup(0)
data ends
stack segment
dw 32 dup(0)
stack ends
code segment
start:
mov bx, data
mov ds, bx ;定位数据段
mov di, 0
mov si, 12
mov bx, stack ;设置栈段地址
mov ss, bx
mov sp, 32
mov cx, 6 ;循环6次以此处理6个数字
dt_s1:
call dtoc
loop dt_s1
mov dh, 8 ;行号, 输入行号
mov dl, 3 ;列号, 输入列号
mov cl, 2 ;颜色-绿色
mov ax, 0B800h ;设置显存目标段
mov es,ax
call show_str ;在屏幕的给点定行列,用给定颜色显示字符串
mov ax, 04c00h
int 21h
;-------------------------------------------------------------------------------
dtoc:
push ax
push cx
push bx
push dx
mov ax,ds:[di] ;被除数
add di, 2
mov bx, 0 ;存储位数
dt_beg:
mov dx, 0
mov cx, 10
div cx
mov cx ,ax
inc bx
add dx,030h
push dx
jcxz dt_end
jmp short dt_beg
dt_end: mov cx, bx
dt_lo: pop ds:[si]
inc si
loop dt_lo
pop dx
pop bx
pop cx
pop ax
ret
;-------------------------------------------------------------------------------
show_str: ;这个程序改变了ax, cx, si , di
push ax
push si
push cx
mov al, 0a0h ;计算目标行
mul dh
mov si, ax
mov al, 02h ;计算目标列,列减1,是因为列是从0开始计算的,行不减,因为在执行程序的过程中,会刷新掉第1行,直接显示第2行
sub dl, 01h
mul dl
add si, ax
mov al, cl ;颜色
showBeg1: mov cl, ds:[di] ;在ds处取出数据,写入现存
mov ch, 0
mov es:[si], cl
jcxz showEnd1 ;如果cx = 0,说明遇见了字符串结尾符0, 我们跳出循环
inc di ;准备写出下一个字符
inc si ;递增到刚写入字符,的颜色内存(一个字节)
mov es:[si], al ;写入颜色
inc si ;准备接受下一个字符
jmp short showBeg1 ;无条件跳转
showEnd1: pop cx
pop si
pop ax
ret
;-------------------------------------------------------------------------------
code ends
end start
转载自网络