求基于Intel 8086的64位双操作数四则运算完整程序
8086汇编实现64位四则运算完整程序
在8086这类16位处理器上,64位操作数需要拆分为4个连续的16位字(小端序存储:低地址存低16位,高地址存高16位)。以下是实现64位加、减、乘、除的完整汇编程序,包含测试逻辑。
核心运算子程序
1. 64位加法(带进位)
从低到高依次对每个16位字执行带进位相加,最终进位标志CF表示是否溢出。
; 输入:SI指向第一个64位操作数的低16位地址,DI指向第二个64位操作数的低16位地址 ; 输出:结果覆盖第一个操作数的内存,CF=1表示加法溢出 add64: push ax push bx push cx mov cx, 4 ; 循环处理4个16位字 clc ; 初始化进位标志为0 add_loop: mov ax, [di] adc [si], ax ; 带进位相加 inc si inc di loop add_loop pop cx pop bx pop ax ret
2. 64位减法(带借位)
从低到高依次对每个16位字执行带借位相减,CF标志表示结果是否为负(需取补码还原)。
; 输入:SI指向被减数低16位地址,DI指向减数低16位地址 ; 输出:结果覆盖被减数内存,CF=1表示不够减(结果为负) sub64: push ax push bx push cx mov cx, 4 clc ; 初始化借位标志为0 sub_loop: mov ax, [di] sbb [si], ax ; 带借位相减 inc si inc di loop sub_loop pop cx pop bx pop ax ret
3. 64位乘法(结果为128位)
通过拆分64位操作数为4个16位字,模拟竖式乘法累加,最终得到128位结果。
; 输入:SI指向第一个64位操作数低16位,DI指向第二个64位操作数低16位,BX指向128位结果的低16位地址 ; 输出:128位结果存入BX指向的内存区域 si_base dw 0 di_base dw 0 mul64: push ax push bx push cx push dx push si push di push bp mov bp, bx ; 保存结果起始地址 ; 初始化结果为0 mov cx, 8 mov bx, bp init_res: mov word ptr [bx], 0 add bx, 2 loop init_res mov cx, 4 ; 遍历第一个数的4个16位部分 mov si_base, si x_loop: mov ax, [si] cmp ax, 0 je x_next ; 当前部分为0,跳过乘法 mov di_base, di mov dx, 4 ; 遍历第二个数的4个16位部分 y_loop: mov bx, [di] mul bx ; 16位乘法,结果存于DX:AX ; 计算结果的偏移位置 mov bx, 8 sub bx, cx sub bx, dx shl bx, 1 add bx, bp ; 累加结果到对应位置,处理进位 add [bx], ax adc [bx+2], dx adc [bx+4], 0 adc [bx+6], 0 adc [bx+8], 0 adc [bx+10], 0 adc [bx+12], 0 adc [bx+14], 0 add di, 2 dec dx jnz y_loop x_next: add si, 2 dec cx jnz x_loop pop bp pop di pop si pop dx pop cx pop bx pop ax ret
4. 64位除法(64位被除数÷64位除数)
通过循环左移余数并尝试减去除数的方式,模拟长除法,最终得到64位商和余数。
; 输入:SI指向被除数低16位,DI指向除数低16位,BX指向商的低16位地址,BP指向余数的低16位地址 ; 输出:商存入BX指向内存,余数存入BP指向内存 di_divisor dw 0 div64: push ax push bx push cx push dx push si push di push bp ; 复制被除数到余数区域(初始余数=被除数) mov cx, 4 mov si, offset num1 mov di, offset remainder copy_dividend: mov ax, [si] mov [di], ax add si, 2 add di, 2 loop copy_dividend ; 初始化商为0 mov cx, 4 mov di, offset quotient init_quotient: mov word ptr [di], 0 add di, 2 loop init_quotient mov cx, 64 ; 循环处理64位 div_loop: ; 余数左移1位 push cx mov cx, 4 clc mov bp, offset remainder shift_remainder: mov ax, [bp] rcl ax, 1 mov [bp], ax add bp, 2 loop shift_remainder pop cx ; 尝试减去除数 push si push di mov si, offset remainder mov di, offset num2 call sub64 pop di pop si jnc set_bit ; 无借位表示余数≥除数,商的当前位置1 ; 有借位则恢复余数(加回除数) push si push di mov si, offset remainder mov di, offset num2 call add64 pop di pop si jmp next_bit set_bit: mov di, offset quotient mov ax, [di] or ax, 1 mov [di], ax next_bit: ; 商左移1位 push cx mov cx, 4 clc mov bx, offset quotient shift_quotient: mov ax, [bx] rcl ax, 1 mov [bx], ax add bx, 2 loop shift_quotient pop cx dec cx jnz div_loop pop bp pop di pop si pop dx pop cx pop bx pop ax ret
完整测试程序
stack segment stack dw 100h dup(?) stack ends data segment ; 测试数据:num1=0x0000000000000001,num2=0x0000000000000002 num1 dw 1, 0, 0, 0 ; 低16位到高16位依次存储 num2 dw 2, 0, 0, 0 result dw 8 dup(0) ; 128位乘法结果存储区 quotient dw 4 dup(0) ; 除法商存储区 remainder dw 4 dup(0) ; 除法余数存储区 msg_add db '64位加法完成', 0dh, 0ah, '$' msg_sub db '64位减法完成', 0dh, 0ah, '$' msg_mul db '64位乘法完成', 0dh, 0ah, '$' msg_div db '64位除法完成', 0dh, 0ah, '$' data ends code segment assume cs:code, ds:data, ss:stack start: mov ax, data mov ds, ax ; 测试加法:num1 = num1 + num2 mov si, offset num1 mov di, offset num2 call add64 mov dx, offset msg_add mov ah, 09h int 21h ; 测试减法:num1 = num1 - num2(此时num1为3,减2得1) mov si, offset num1 mov di, offset num2 call sub64 mov dx, offset msg_sub mov ah, 09h int 21h ; 测试乘法:num1 * num2 = 2,结果存入result mov si, offset num1 mov di, offset num2 mov bx, offset result call mul64 mov dx, offset msg_mul mov ah, 09h int 21h ; 测试除法:num1(1)÷ num2(2),商0,余数1 mov si, offset num1 mov di, offset num2 mov bx, offset quotient mov bp, offset remainder mov di_divisor, di call div64 mov dx, offset msg_div mov ah, 09h int 21h ; 程序退出 mov ah, 4ch int 21h ; 插入上述所有子程序 add64: push ax push bx push cx mov cx, 4 clc add_loop: mov ax, [di] adc [si], ax inc si inc di loop add_loop pop cx pop bx pop ax ret sub64: push ax push bx push cx mov cx, 4 clc sub_loop: mov ax, [di] sbb [si], ax inc si inc di loop sub_loop pop cx pop bx pop ax ret si_base dw 0 di_base dw 0 mul64: push ax push bx push cx push dx push si push di push bp mov bp, bx mov cx, 8 mov bx, bp init_res: mov word ptr [bx], 0 add bx, 2 loop init_res mov cx, 4 mov si_base, si x_loop: mov ax, [si] cmp ax, 0 je x_next mov di_base, di mov dx, 4 y_loop: mov bx, [di] mul bx mov bx, 8 sub bx, cx sub bx, dx shl bx, 1 add bx, bp add [bx], ax adc [bx+2], dx adc [bx+4], 0 adc [bx+6], 0 adc [bx+8], 0 adc [bx+10], 0 adc [bx+12], 0 adc [bx+14], 0 add di, 2 dec dx jnz y_loop x_next: add si, 2 dec cx jnz x_loop pop bp pop di pop si pop dx pop cx pop bx pop ax ret di_divisor dw 0 div64: push ax push bx push cx push dx push si push di push bp mov cx, 4 mov si, offset num1 mov di, offset remainder copy_dividend: mov ax, [si] mov [di], ax add si, 2 add di, 2 loop copy_dividend mov cx, 4 mov di, offset quotient init_quotient: mov word ptr [di], 0 add di, 2 loop init_quotient mov cx, 64 div_loop: push cx mov cx, 4 clc mov bp, offset remainder shift_remainder: mov ax, [bp] rcl ax, 1 mov [bp], ax add bp, 2 loop shift_remainder pop cx push si push di mov si, offset remainder mov di, offset num2 call sub64 pop di pop si jnc set_bit push si push di mov si, offset remainder mov di, offset num2 call add64 pop di pop si jmp next_bit set_bit: mov di, offset quotient mov ax, [di] or ax, 1 mov [di], ax next_bit: push cx mov cx, 4 clc mov bx, offset quotient shift_quotient: mov ax, [bx] rcl ax, 1 mov [bx], ax add bx, 2 loop shift_quotient pop cx dec cx jnz div_loop pop bp pop di pop si pop dx pop cx pop bx pop ax ret code ends end start
注意事项
- 上述程序默认处理无符号数,若需处理有符号数:减法后若
CF=1,需对结果取补码;乘法/除法需先记录操作数符号,最终为结果添加对应符号。 - 程序采用MASM语法,可通过MASM/TASM编译,在DOSBox或8086模拟器中运行。
- 乘法结果为128位,需预留8个16位字的内存空间;除法的商和余数均为64位。
内容的提问来源于stack exchange,提问作者user25042064
相关产品推荐
相关产品推荐

