预备知识:
(1)
ret :修改IP IP = SS*16 + SP SP+=2
retf :修改CS,IP IP = SS*16 + SP ,SP+=2 , CS = SS*16 + SP , SP+=2
Source Code:
assume cs:code stack segment db 16 dup (0) stack ends code segment mov ax,4c00H int 21H start: mov ax,stack mov ss,ax mov sp,16 mov ax,0 push ax mov bx,0 ret code ends end start
IP指向了栈顶元素,栈顶元素等于0,那么下一条命令就是返回程序;
Source Code:
assume cs:code stack segment db 16 dup (0) stack ends code segment mov ax,4c00h int 21h start: mov ax,stack mov ss,ax mov sp,16 mov ax,0 push cs push ax mov bx,0 retf code ends end start
IP还是指向栈顶元素,下一条命令是返回程序;
也就是说,
ret 相当于 pop IP;
retf 相当于 pop IP,pop CS;
(2)call:内存中转移
call word ptr 相当于 push IP,jmp word ptr
call dword ptr 相当于 push CS,push IP,jmp dword ptr
Source Code:
assume cs:code stack segment dw 8 dup (0) stack ends code segment start: mov ax,stack mov ss,ax mov sp,16 mov ds,ax mov ax,0 call word ptr ds:[0EH] inc ax inc ax inc ax mov ax,4c00H int 21H code ends end start
(3)mul,乘法指令
1、8位,一个数在AL中,一个在内存中,结果在AX中
2、16位,一个在AX中,一个在内存中,结果,高位在DX中,低位在AX中;
(4)call和ret的配合:模块化程序
Source Code:
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 si,0 mov di,16 mov cx,8 s: mov bx,[si] call cube mov [di],ax mov [di].2,dx add si,2 add di,4 loop s mov ax,4c00H int 21H cube: mov ax,bx mul bx mul bx ret code ends end start
(5)批量数据传递,放到内存中,或者栈中;
Source Code:
assume cs:code data segment db 'conversation' data ends code segment start: mov ax,data mov ds,ax mov si,0 mov cx,12 call capital mov ax,4c00h int 21h capital: and byte ptr [si],11011111b inc si loop capital ret code ends end start
(6)解决寄存器的冲突,就是将子程序用到的寄存器入栈;
Source Code:
assume cs:code data segment db 'word',0 db 'unix',0 db 'wind',0 db 'good',0 data ends code segment start: mov ax,data mov ds,ax mov bx,0 mov cx,4 s: mov si,bx call capital call change add bx,5 loop s mov ax,4c00h int 21h capital: push cx push si change: mov cl,[si] mov ch,0 jcxz ok and byte ptr [si],11011111b inc si jmp short capital ok: pop si pop cx ret code ends end start
试验任务:
显示字符串(注意DOS下一列占两个字符)
Source Code:
assume cs:code data segment db 'I am TreeDream!',0 data ends code segment start: mov dh,8 mov dl,3 mov cl,2 mov ax,data mov ds,ax mov si,0 call show_str mov ax,4c00H int 21H show_str: push dx push cx push ax push ss push si mov ax,0B800H mov es,ax ;用于显示的栈段 mov al,0a0h dec dh ;行数以0标号 mul dh ;行的偏移 mov bx,ax mov al,2 ;dos显示一列占两个字节 dec dl mul al add bx,ax ;显示的起始地址计算完 mov di,0 ;数据段指针 mov si,0 mov al,cl ;cx用于循环 s: mov ch,0 mov cl,ds:[di] jcxz ok ;判断cx是否为0 mov ch,al mov es:[bx+si],cx ;显示 add si,2 inc di jmp short s ok: pop si pop ss pop ax pop cx pop dx ret code ends end start
(2)除法溢出
assume cs:code,ss:stack stack segment dw 8 dup (0) stack ends code segment start: mov ax,stack mov ss,ax mov sp,16 mov ax,1000H mov dx,1 mov bx,1 div bx mov ax,4c00h int 21h code ends end start
除法的结果超过16为,ax中存不下;
解决方案,公式是X/N = int(H/N)*65536 + (rem(H/N)*65536 + L) / N
公式很好理解,但是程序不是很好理解;
Source Code:
assume cs:code,ss:stack stack segment dw 8 dup (0) stack ends code segment start: mov ax,stack mov ss,ax mov sp,16 mov ax,4240H mov dx,00fH mov cx,0aH call divdw mov ax,4c00h int 21h divdw: push ax mov ax,dx mov dx,0 div cx mov bx,ax pop ax div cx mov cx,dx mov dx,bx ret code ends end start
第一次除法:
ax = 1,dx = 5
第二次除法的时候,第一次的除法余数将是第二次除法的高位
(3)数值显示
Source Code:
assume cs:code data segment db 10 dup (0) data ends stack segment dw 8 dup(0) stack ends code segment start: mov ax,42243 mov bx,data mov ds,bx mov bx,stack mov ss,bx mov sp,10h mov si,0 call dtoc mov dh,8 mov dl,3 mov cl,2 call show_str mov ax,4c00h int 21h dtoc: push ax push bx push si mov bx,10 mov si,0 s0: mov dx,0 div bx ;dx 余数,ax商 add dx,30h ;余数入栈 push dx mov cx,ax ;一直除到商为0 inc si inc cx ;每次循环cx会减1,然而cx是用来存商的; loop s0 mov cx,si ;cx循环次数,即有多少位 mov si,0 s1: pop ds:[si] inc si loop s1 pop si pop bx pop ax ret show_str: push ax push dx push cx push si mov di,0 mov bl,dh dec bl mov al,160 mul bl mov bx,ax add dl,dl add bl,dl mov ax,0b800h mov es,ax mov al,cl s: mov ch,0 mov cl,ds:[si] jcxz ok mov es:[bx+di],cl mov es:[bx+di+1],al add di,2 inc si loop s ok: pop si pop cx pop dx pop ax ret code ends end start