;显示 123, 12666, 1, 8, 3, 38 的程序如下:
CCC SEGMENTDW 123, 12666, 1, 8, 3, 38
BG:
PUSH CS
POP DS
;-----------------------
MOV SI, 0
MOV DI, 0506H ;显示屏的偏移地址
MOV CX, 6 ;6个数据
@@: PUSH CX
CALL DTOC ;调用函数,将整型转化为字符串,在显示屏显示
ADD SI, 2
ADD DI, 2 ;DI指向下一个显示的位置
POP CX
LOOP @B
MOV AH, 4CH
INT 21H
;-----------------------------------
DTOC:
MOV AX, [SI]
MOV BX, 10
MOV CX, 0
@@: SUB DX, DX ;DX清零
DIV BX
PUSH DX
INC CX
CMP AX, 0
JNZ @B
MOV AH, 2
@@: POP DX
CALL SHOW_STR ;每求的一个余数就调用显示函数
LOOP @B
RET
;-----------------------------------
SHOW_STR: ;显示每个数据除10后的余数功能
MOV BX, 0B800H
MOV ES, BX
ADD DX, 4A30H ;余数转化为ASCII码进行显示
MOV ES:[DI], DX
ADD DI, 2 ;DI指向下一个显示的位置
RET
;-----------------------------------
CCC ENDS
END BG
CPU 执行除法指令时,是有可能溢出的。这在教材上,是有明显的提示的。
如果被除数较大,或除数较小,都可能使“商”超出预定位数,此时,就会溢出。
特别是当除数为零时,必然会出现:Divide overflow。
除法溢出,问题很严重。一旦出现除法溢出,系统就崩溃了。
(补码加减运算,也会有溢出,但是,没有崩溃的危险。)
王爽在教材上,给出了一个“不会溢出”编程思路。可实现“双字/一字”。
这程序的编程思路,本来是很简单,但是被他写的,简直就是一塌糊涂。
“字除法”的指令是:DIV CX。
CPU 的 *** 作,就是:( DX : AX ) / CX = AX DX。
按照你的应用举例:1000000 / 10 (即:000F 4240H / 000AH)。
如果用“字除法”,简单说就是“把高位字、低位字,分别除以 CX”。
即,第一步:用 0000 000FH 除以 000AH,得到高位商 0001、高位余数 0005。
第二步:用 0005 4240H 除以 000AH,可得到低位商 86A0H、低位余数 0000。
这种计算方法,完全可以用小学用的“竖式”来描述:
以小学生的水平,就可以理解这个图了。
-----------------------
就这么一个简单问题,你看王爽写的多么滥:
公式:X/N = int(H/N)65536 + [rem(H/N)65536 + L]/N
X:被除数,范围
N:除数,范围
H:X的高16位
L:X的低16位
int():描述性运算符,取商
ram():描述性运算符,取余数
功能:进行不会产生溢出的除法运算,被除数为dword型,除数为word型,结果为dword型
参数:
(ax)=dword型数据的低16位
(dx)=dword型数据的高16位
(cx)=除数
-----------------------
按照你提供的数据,程序,应该如下编写:
START:
MOV DX, 000FH ;被除数的高16位
MOV AX, 4240H ;被除数的低16位
MOV CX, 000AH ;16位
CALL DIVDW;32位数除以16位数
MOV AX, 4C00H
INT 21H
;--------------
DIVDW: ;DX:AX / CX = DX:AX CX
PUSH BX
MOV BX,AX ;保存被除数的低16位
MOV AX,DX ;高16位放在低16
MOV DX,0 ;高16改为0
DIV CX ;
PUSH AX ;保存高16位商
;DX中是余数
MOV AX,BX ;恢复低16位数
DIV CX ;(余数与低16)除以除数
MOV CX,DX ;余数存到CX
POP DX ;商的高16位数送到DX
POP BX ;恢复现场
RET
-----------------------
通用的思路方法,如下:
按照图中的步骤,执行四次 DIV BL,即可实现“四个字节/一个字节”。
只要 BL 不为零,就绝对不会发生溢出。
按此思路,被除数的字节数,可以继续增加,仅受制于内存的大小。
绝不限于王爽所介绍的 DIVDW 所用的双字。
这个问题碰到好多人提问了。
关键是你用到的t命令影响了栈。
t是单步调试命令,当使用单步调试时,实际产生了单步中断。CPU会自动把一些值存放到栈中,这样实际上就会把你在程序里压入栈的值给覆盖掉。
你注意看最后一次的r输出,2000:0eh = 3123h,这个结果是正确的,就是你第一次压入到栈里的ax。而2000:08h = 010fh,2000:0ah = 073fh,而073fh:010fh就是push ax这条指令的地址。CPU在你用t命令单步调试的时候,自动做了一些压栈 *** 作。
所以,如果你用t命令调试程序,建议你把sp设置大点。比如mov sp, 100h
另外,由于栈是向下生长的,而单步调试时CPU又会把一些标志放到栈里,所以栈的小地址里的内容,是不确定的,你就不要纠结从0开始的这部分内存了。只关注SP那一块的内容就行了。
(R2R3)(R6R7)乘以两个16位的无符号数,结果(R4R5R6R7)
MOV A,R3
MOV B,R7
MUL AB
XCH A ,R7
MOV R5,B
MOV B,R2
MUL AB
ADD A,R5
MOV R4,一个
CLR A
ADDC A,B
一个
MOV A,R6
MOV B,MOV R5,R3
MUL AB
ADD A,R4
XCH A,R6
XCH A,B
ADDC A,R5
MOV R5,一个
MOV F0,C
MOV A,R2
MUL AB
ADD A,R5
MOV R5,一个
CLR A
MOV ACC0,C
MOV C,F0
ADDC A,B
MOV R4 ,A
;
DATA SEGMENT
VAR_B DB 2 DUP()
VAR_W DW 2 DUP()
VAR_D DD 2 DUP()
DATA ENDS
;
EXTRA SEGMENT
VAR_BYTE DB 1,2
VAR_WORD DW 1234H,5678H
VAR_DWORD DD 5,6
EXTRA ENDS
;
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,ES:EXTRA
START:
MOV AX,DATA
MOV DS,AX
MOV AX,EXTRA
MOV ES,AX
MOV AL,VAR_BYTE
MOV AH,VAR_BYTE+1
MOV VAR_B,AL
MOV VAR_B,AH;直接寻址
MOV BX,ES:VAR_WORD
MOV AX,ES:[BX]
MOV VAR_W,AX
MOV AX,ES:[BX+2]
MOV VAR_W+2,AX;寄存器间接
MOV SI,0
MOV EAX,ES:VAR_DWORD [SI]
MOV VAR_D,EAX
MOV EAX,ES:VAR_DWORD[SI+4]
MOV VAR_D,EAX
MOV AX,4C00H
INT 21H
CODE ENDS
END START
1将80C51片内RAM的20H~2EH共15个单元置以初值0A0H~0AEH,
mov r0,#20H
mov a,#0a0h
loop:
mov @r0,a
inc r0
inc a
cjne r0,#2fh,loop
然后再将8700H~870EH单元的内容传送到片内RAM的60H~6EH中。
mov dptr,#8700h
mov r0,#60h
loop2:
movx a,@dptr
mov @r0,a
inc dptr
inc r0
mov a,dpl
cjne a,#0fh,loop2
最后将20H~2EH单元的内容传送到片外RAM的8700H~870EH
mov dptr,#8700h
mov r0,#20h
loop3:
mov a,@r0
movx @dptr,a
inc dptr
inc r0
cjne r0,#2fh,loop3
end
2用P1口的p10-p17八个端口做输出口,接8只发光二极管(LED),编写程序使LED循环点亮。
mov a,#1
loop:
rl a
mov p1,a
;delay
mov r1,#0ffh
loop2:mov r2,#0ffh
djnz r2,$
djnz r1,loop2
;delay end
sjmp loop
end
3题目: P1口接8只发光二极管(L0~L7), T1作定时器,系统晶振6MHz。编写程序,让第1秒时L0~L3点亮, L4~L7暗;第2秒时L0~L3暗, L4~L7亮;第3秒时L0~L7全亮;第4秒时L0~L7全暗;第5秒时L0~L3点亮, L4~L7暗;如此循环下去
;这个有点复杂了……
org 0h
sjmp start
org 0bh
mov th0,#0bh
mov tl0,#0dch
inc r7;R7是计数器,满8次表示1秒到了
cjne r7,#8,exit
mov r7,#0
inc r6
cjne r6,#4,skip
mov r6,#0
skip:
mov a,r6
movc a,@a+dptr
mov p1,a
exit:reti
start:
mov tmod,#1
setb ea
setb et0
setb tr0
mov dptr,#tab
sjmp $
tab:db 0f0h,0fh,0h,0ffh
1题 2题
dseg segment
a1 dw 12,34,56,78,90,21,43,65,87,9
c equ ($-a1)/2
a2 dw 0
dseg ends
assume cs:cseg, ds:dseg
cseg segment
start:
mov ax, dseg
mov ds, ax
;
mov cx, c
dec cx
mov bx, 2
mov ax, a1[0]
$8:
cmp ax, a1[bx]
ja $9
mov ax,a1[bx]
$9:
inc bx
inc bx
loop $8
mov a2, ax
call print
mov ah,0eh
mov al,0dh
int 10h
mov al,0ah
int 10h
mov cx, c2
dec cx
dec cx
$0:
mov bx, 0
$2:
mov ax, a1[bx]
cmp ax, a1[bx+2]
ja $1
xchg ax,a1[bx+2]
mov a1[bx], ax
$1:
inc bx
inc bx
cmp bx, cx
jl $2
dec cx
dec cx
jg $0
;print result
mov cx, c
mov bx, 0
$3:
mov ax, a1[bx]
call print
mov ax,0e20h
int 10h
inc bx
inc bx
loop $3
mov ah,4ch
int 21h
print proc near
push cx
push bx
xor cx, cx
mov bx, 10
Q0:
xor dx, dx
div bx
xor dx,0e30h
push dx
inc cx
cmp ax, 0
jnz Q0
Q1:
pop ax
int 10h
loop Q1
pop bx
pop cx
ret
print endp
cseg ends
end start
实验5 编写、调试具有多个段的程序
-----------------------------------------
(1)
1保持不变
2<考虑不同机子环境不同,答案无法统一>
3X-2,X-1
(2)
1保持不变
2<考虑不同机子环境不同,答案无法统一>
3X-2,X-1
4(N/16+1)16 [说明:N/16只取整数部分]
(3)
1保持不变
2<考虑不同机子环境不同,答案无法统一>
3X+3,X+4
(4)
答:第3个仍然可以正确执行。因为如果把end指令后的标号start去掉后,编译器便会顺序执行程序。换句话说:当未给编译器预先的通知,要求其从哪开始执行程序时,编译器就自动以'至上向下'的顺序进行编译执行源程序。
(5)完整程序如下:
assume cs:code
a segment
db 1,2,3,4,5,6,7,8
a ends
b segment
db 1,2,3,4,5,6,7,8
b ends
c segment
db 0,0,0,0,0,0,0,0
c ends
code segment
start:mov ax,a
mov es,ax
mov ax,c
mov ds,ax
mov bx,0
mov cx,8
s1:mov ax,es:[bx]
add [bx],ax
add bx,2
loop s1
mov ax,b
mov es,ax
mov ds,ax
mov bx,0
mov cx,8
s2:mov ax,es:[bx]
add [bx],ax
add bx,2
loop s2
mov ax,4c00h
int 21h
code ends
end start
(6)完整程序如下:
assume cs:code
a segment
dw 1,2,3,4,5,6,7,8
a ends
b segment
dw 0,0,0,0,0,0,0,0
b ends
code segment
start:
mov ax,b
mov ss,ax
mov sp,10h
mov ax,a
mov ds,ax
mov bx,0
mov cx,8
s: push [bx]
add bx,2
loop s
mov ax,4c00h
int 21h
code ends
end start
实验6 实践课程中的程序
-------------------------------
(2)编程:完成问题中的程序。
问题79完整程序如下:
assume cs:codesg,ss:stacksg,ds:datasg
stacksg segment
dw 0,0,0,0,0,0,0,0
stacksg ends
datasg segment
db '1 display '
db '2 brows '
db '3 replace '
db '4 modify '
datasg ends
codesg segment
start:
mov ax,stacksg
mov ss,ax
mov sp,16
mov ax,datasg
mov ds,ax
mov bx,0
mov cx,4
s: ;外循环
push cx
mov si,3
mov cx,4
s0: ;内循环
mov al,[bx+si]
and al,11011111b
mov [bx+si],al
inc si
loop s0
add bx,16
pop cx
loop s
mov ax,4c00h
int 21h
codesg ends
end start
以上就是关于汇编语言(王爽第三版)实验十 怎么做的,我做得结果和正确答案有偏差,望指点迷津全部的内容,包括:汇编语言(王爽第三版)实验十 怎么做的,我做得结果和正确答案有偏差,望指点迷津、百思不得其解,一道汇编语言的题(王爽编的汇编语言中实验10.2)、王爽汇编语言 实验2实验任务2 希望有人解答下啊!!!等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)