汇编语言(王爽第三版)实验十 怎么做的,我做得结果和正确答案有偏差,望指点迷津

汇编语言(王爽第三版)实验十 怎么做的,我做得结果和正确答案有偏差,望指点迷津,第1张

;显示 123, 12666, 1, 8, 3, 38 的程序如下:

CCC   SEGMENT

    DW   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 希望有人解答下啊!!!等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/9467575.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-28
下一篇 2023-04-28

发表评论

登录后才能评论

评论列表(0条)

保存