汇编求平方根的问题,急

不能吃辣了orz 2005-09-02 03:25:18
屏幕上任意输入0-65535范围内的数,显示出其平方根,按Q退出程序,按N继续下一轮输入

求算法,本人菜鸟不知如何下手,恳请高手赐教!!!
...全文
1276 35 打赏 收藏 转发到动态 举报
写回复
用AI写文章
35 条回复
切换为时间正序
请发表友善的回复…
发表回复
不能吃辣了orz 2005-09-12
  • 打赏
  • 举报
回复
真是不好意思,这几天忙着上课,忘记给分了,汗。。。
作业应该搞定了,非常非常感谢你!!!
liangbch 2005-09-09
  • 打赏
  • 举报
回复
第二个 cmp al,'Y' 应改为cmp al,'y'。
如果确实需要,N 继续, Q 退出的话,可修改这四个cmp语句,并将修改提示信息"Continue?(Y/N)?"


liangbch 2005-09-09
  • 打赏
  • 举报
回复
笔误,在最后,多打了一个 public,删除也可。
liangbch 2005-09-09
  • 打赏
  • 举报
回复
这和com格式没有关系,编写com文件需要:
1.第一条指令从100h开始,org 100h,就是为这个用的。不需要设置cs,ds.
2.数据和代码 必须定义在同一个段。

框架己经搭好来,你只需添加代码就行了。算了,我写一个完整的程序算了,省得你又搞不定。
.MODEL TINY

_TEXT segment
org 100h

_main proc near
; printf prompt string

main_start:
call _clearBuff

mov dx,offset DGROUP:_promptStr
mov ah,09h
int 21h
;
call _inputNum
cmp _result,0ffffh
jz display_error

call _my_sqrt
call _outputNum

; printf prompt string

error_char:
mov dx,offset DGROUP:_promptStr2
mov ah,09h
int 21h

mov ah,1
int 21h

cmp al,'y'
jz main_start
cmp al,'Y'
jz main_start

cmp al,'n'
jz main_exit

cmp al,'N'
jz main_exit

jmp error_char //既不是 'y' 也不是'n',重新输入

main_exit:
mov ax,4c00h
int 21h
display_error:
mov dx, offset _invalid_input
mov ah,9
int 21h
jmp main_exit
_main endp


; 从控制台输入一个字符串,转化为一个数
_inputNum proc near

;input a string from console
mov dx, offset DGROUP:_inBuff

push dx

mov ah,0ah
int 21h
;
pop si ;输入buff地址
add si,2 ;skip buffer length and actual length
xor ax,ax ;ax 输入数的整数部分
xor cx,cx

converInt:
mov cl,byte ptr [si]
cmp cl,'.'
jnz next
inc si
xor ax,ax ;从现在起,ax表示小数部分
jmp convertFrac
next:
sub cl,'0'
cmp cl,9
ja inputExit ;遇到非数字字符

mov bx,10
mul bx ;dx 进位

add ax,cx
adc dx,0

or dx,dx
jnz error_input ;输入结果大于65535,转错误处理

mov _n_hiWord,ax
inc si
jmp converInt


convertFrac:
cmp _frac_len,4 ;最多允输入4位小数
jge saveFrac

mov cl,byte ptr [si]
sub cl,'0'
cmp cl,9
ja saveFrac ;遇到非数字字符

mov bx,10
mul bx
add ax,cx
inc _frac_len

inc si
jmp convertFrac

saveFrac:
mov bx,4
sub bx,_frac_len
shl bx,1
mov cx, word ptr [_tenPow+bx] ;取数组元素 _tenPow[_4-frac_len], 10的4-_frac_len次方
mul cx ; ;转化到1000-9999之间的数据
mov _n_loWord, ax ;存储

inputExit:
mov ax,_n_hiWord
mov dx,10000
mul dx
add ax,_n_loWord
adc dx,0
mov _n_hiWord,dx
mov _n_loWord,ax
ret
error_input:
mov _result,-1
ret
_inputNum endp


_my_sqrt proc near

mov dx, word ptr _n_hiWord
mov ax, word ptr _n_loWord
mov bx, 8000h ;平方根初值,等于 结果*100
mov cx, 16

;计算平方根的初值x0
start1:
test dx, 0c000h
jne short firstCalc

shl ax, 1 ;dx:ax 联合左移一位
rcl dx, 1

shl ax, 1 ;dx:ax 联合左移一位
rcl dx, 1

shr bx, 1
loop start1

firstcalc:
or bx,bx
jz thisExit ;bx 为0,直接退出

mov cx,3 ;进行第3次迭代
Newton_it:
; 使用牛顿迭法,得到更精确值
; x1= (n/x0 + x0)/2
mov dx, _n_hiWord ;dx:ax 表示 n
mov ax, _n_loWord
div bx ; bx 表示 x0
xor dx,dx

add ax, bx ;这两数之和可能>65536,故用dx:ax 表示
adc dx, 0

shr dx,1 ;dx:ax 除以2
rcr ax,1

mov bx,ax
loop Newton_it ;进行3次迭代,得到精确值
thisExit:
mov _result,bx
ret
_my_sqrt endp


_outputNum proc near

xor dx,dx
mov ax,_result
mov bx,100
div bx ;dx 余数小数部分,ax,整数部分

push dx ;余数,小数部分,保存到栈
mov bx,10
mov di, offset _resultstr+4

intLoop:
or ax,ax
jz printFrac

xor dx,dx
div bx
add dl,'0'
mov [di],dl
dec di
jmp intLoop

printFrac:
pop ax ;小数部分
mov di,offset _resultstr+7

fracLoop:
or ax,ax
jz _displayString

xor dx,dx
div bx
add dl,'0'
mov [di],dl
dec di
jmp fracLoop

_displayString:
mov dx, offset _resultstr
mov ah,9
int 21h
ret
_outputNum endp


_clearBuff proc near
mov ax,0
mov _n_loWord,ax
mov _n_hiWord,ax
mov _frac_len,ax
mov _result,ax

mov bx,offset _resultstr
mov byte ptr [bx],0dh
mov byte ptr [bx+1],0ah

mov byte ptr [bx+2],20h
mov byte ptr [bx+3],20h
mov byte ptr [bx+4],'0'
mov byte ptr [bx+5],'.'
mov byte ptr [bx+6],'0'
mov byte ptr [bx+7],'0'
mov byte ptr [bx+8],'$'
ret
_clearBuff endp


_promptStr label byte
db 0dh
db 0ah
db "calc sqrt(n),(0.00<n<65536.99),n=?"
db '$'

_promptStr2 label byte
db 0dh
db 0ah
db "Continue?(Y/N)?"
db '$'

_invalid_input label byte
db 0dh
db 0ah
db "Invalid input!!!"
db '$'

_tenPow label word ;10的n次方
dw 1
dw 10
dw 100
dw 1000


_n_loWord dw ? ; n*10000 的low word
_n_hiWord dw ? ; n*10000 的high word

_frac_len dw ? ;小数部分长度,最多处理前4位
_result dw ? ;平方根,表示平方根*100


_inBuff label byte
db 12
db 12 dup (?)

_resultstr label byte
db 9 dup (?)

_TEXT ends

public _promptStr
public _main
public _my_sqrt
public _inputNum
public _outputNum
public

end _main

不能吃辣了orz 2005-09-08
  • 打赏
  • 举报
回复
你说的那个清零操作和输出缓冲区初始化我问了周围的人,可惜他不知道.com的格式怎么写。现在我输入一次没问题,第二次求平方根的时候得出的结果就比较怪异了。我们明天最后一天就交了,麻烦你能不能指点一下,实在是不会啊!
liangbch 2005-09-07
  • 打赏
  • 举报
回复
那改动的地方就不止这些了,当第二次计算时,_n_loWord,_n_hiWord,_frac_len,_result 这些变量都得清零。输出缓冲区_resultstr 也得重新初始化。
总体思路,在main函数开始 和 main_exit 之间,改为循环体,循环尾处重新初始变量,输出提示信息,输入一个字符,判断是 N 转循环头,否则接着往下执行。

不能吃辣了orz 2005-09-07
  • 打赏
  • 举报
回复
我试过了,换成.com就是没问题了。我想实现输入Q退出,输入N继续下一轮输入,我在next:里加了语句,但无法编译,应该在哪个地方加呢?输入N继续输入怎么实现?我好菜啊!!!
不能吃辣了orz 2005-09-07
  • 打赏
  • 举报
回复
.com的格式好像不一样啊,没学过这种,不过q退出实现了
liangbch 2005-09-06
  • 打赏
  • 举报
回复
我试过了,用tasm + tlink生成的exe 的确有这个问题,但转成com就没有问题了,但ml + tlink生成的的exe 和com 都没有问题。
不能吃辣了orz 2005-09-06
  • 打赏
  • 举报
回复
这个帖先留着,你去我开的那个计算器的帖吧,随便发个言
不能吃辣了orz 2005-09-06
  • 打赏
  • 举报
回复
需要怎么改吗
不能吃辣了orz 2005-09-06
  • 打赏
  • 举报
回复
我是tasm...
liangbch 2005-09-06
  • 打赏
  • 举报
回复
还是公布在本社区吧,这样对别人也会有帮助。

.MODEL TINY

_TEXT segment
org 100h

_main proc near
; printf prompt string
mov dx,offset DGROUP:_promptStr
mov ah,09h
int 21h
;
call _inputNum
cmp _result,0ffffh
jz display_error

call _my_sqrt
call _outputNum
main_exit:
mov ax,4c00h
int 21h
display_error:
mov dx, offset _invalid_input
mov ah,9
int 21h
jmp main_exit
_main endp


; 从控制台输入一个字符串,转化为一个数
_inputNum proc near

;input a string from console
mov dx, offset DGROUP:_inBuff

push dx

mov ah,0ah
int 21h
;
pop si ;输入buff地址
add si,2 ;skip buffer length and actual length
xor ax,ax ;ax 输入数的整数部分
xor cx,cx

convertInt:
mov cl,byte ptr [si]
cmp cl,'.'
jnz next
inc si
xor ax,ax ;从现在起,ax表示小数部分
jmp convertFrac
next:
sub cl,'0'
cmp cl,9
ja inputExit ;遇到非数字字符

mov bx,10
mul bx ;dx 进位

add ax,cx
adc dx,0

or dx,dx
jnz error_input ;输入结果大于65535,转错误处理

mov _n_hiWord,ax
inc si
jmp convertInt


convertFrac:
cmp _frac_len,4 ;最多允输入4位小数
jge saveFrac

mov cl,byte ptr [si]
sub cl,'0'
cmp cl,9
ja saveFrac ;遇到非数字字符

mov bx,10
mul bx
add ax,cx
inc _frac_len

inc si
jmp convertFrac

saveFrac:
mov bx,4
sub bx,_frac_len
shl bx,1
mov cx, word ptr [_tenPow+bx] ;取数组元素 _tenPow[_4-frac_len], 10的4-_frac_len次方
mul cx ; ;转化到1000-9999之间的数据
mov _n_loWord, ax ;存储

inputExit:
mov ax,_n_hiWord
mov dx,10000
mul dx
add ax,_n_loWord
adc dx,0
mov _n_hiWord,dx
mov _n_loWord,ax
ret
error_input:
mov _result,-1
ret
_inputNum endp


_my_sqrt proc near

mov dx, word ptr _n_hiWord
mov ax, word ptr _n_loWord
mov bx, 8000h ;平方根初值,等于 结果*100
mov cx, 16

;计算平方根的初值x0
start1:
test dx, 0c000h
jne short firstCalc

shl ax, 1 ;dx:ax 联合左移一位
rcl dx, 1

shl ax, 1 ;dx:ax 联合左移一位
rcl dx, 1

shr bx, 1
loop start1

firstcalc:
or bx,bx
jz thisExit ;bx 为0,直接退出

mov cx,3 ;进行第3次迭代
Newton_it:
; 使用牛顿迭法,得到更精确值
; x1= (n/x0 + x0)/2
mov dx, _n_hiWord ;dx:ax 表示 n
mov ax, _n_loWord
div bx ; bx 表示 x0
xor dx,dx

add ax, bx ;这两数之和可能>65536,故用dx:ax 表示
adc dx, 0

shr dx,1 ;dx:ax 除以2
rcr ax,1

mov bx,ax
loop Newton_it ;进行3次迭代,得到精确值
thisExit:
mov _result,bx
ret
_my_sqrt endp


_outputNum proc near

xor dx,dx
mov ax,_result
mov bx,100
div bx ;dx 余数小数部分,ax,整数部分

push dx ;余数,小数部分,保存到栈
mov bx,10
mov di, offset _resultstr+3

intLoop:
or ax,ax
jz printFrac

xor dx,dx
div bx
add dl,'0'
mov [di],dl
dec di
jmp intLoop

printFrac:
pop ax ;小数部分
mov di,offset _resultstr+6

fracLoop:
or ax,ax
jz _displayString

xor dx,dx
div bx
add dl,'0'
mov [di],dl
dec di
jmp fracLoop

_displayString:
mov dx, offset _resultstr
mov ah,9
int 21h
ret
_outputNum endp


_promptStr label byte
db "calc sqrt(n),(0.00<n<65536.99),n=?"
db '$'


_invalid_input label byte
db 0ah
db "Invalid input!!!"
db '$'

_resultstr label byte
db 0ah
db 20h
db 20h
db '0'
db '.'
db '0'
db '0'
db '$'


_tenPow label word ;10的n次方
dw 1
dw 10
dw 100
dw 1000


_n_loWord dw 0 ; n*10000 的low word
_n_hiWord dw 0 ; n*10000 的high word

_frac_len dw 0 ;小数部分长度,最多处理前4位
_result dw 0 ;平方根,高8位表示整数部分,低8位表示小数部分

_inBuff label byte
db 12

_TEXT ends

public _promptStr
public _main
public _my_sqrt
public _inputNum
public _outputNum

end _main

liangbch 2005-09-06
  • 打赏
  • 举报
回复
你用的不什么编译器,你编译后的程序是exe 还是com.我的编译命令行是:

ml /AT /c sqrt.asm
tlink sqrt.obj
exe2bin sqrt.exe sqrt.com

我用的是汇编器是 masm 7.0 中的ml.exe, 版本6.14.8444,
tlink 是用turbo c 2.0 中自带的。显示为“Turbo Link Version 2.0 Copyright (c) 1987, 1988 Borland International”

liangbch 2005-09-06
  • 打赏
  • 举报
回复
应改为:
_result dw 0 ;平方根,表示平方根乘以100


好好看看我的程序,争取看懂每一行,不要只为应付老师。如有问题,也可给我发e-mail: liangbch@263.net.

顺便问一下,你是哪个学校,你的老师出的这个题比较有水平,考查点较多,一般在校生是做不出来的。
不能吃辣了orz 2005-09-06
  • 打赏
  • 举报
回复
但不知怎么运行的时候出乱码
不能吃辣了orz 2005-09-06
  • 打赏
  • 举报
回复
感激之情不知道怎么表达了
不能吃辣了orz 2005-09-06
  • 打赏
  • 举报
回复
liangbch(宝宝) :我想了不少时间了,有思路但不会做,我们还要写3000字的报告。你能不能现在把代码发给我呢,我把它看懂后还要加注释写报告,时间快来不及了。谢谢!发我的邮箱也可以:hhdfly2003@126.com,谢谢!
seamine 2005-09-05
  • 打赏
  • 举报
回复
e0100 BA 6A 02 B4 09 CD 21 E8 81 00 83 3E B3 02 00 75
e0110 0B E8 11 00 E8 F8 00 B8 00 4C CD 21 BA 8F 02 B4
e0120 09 CD 21 EB F2 8B 16 AB 02 A1 AD 02 8B DA D1 EA
e0130 D1 EA D1 E8 D1 E8 B1 0E D3 E3 0B C3 89 16 AB 02
e0140 A3 AD 02 BB 00 80 B9 08 00 F7 C2 00 C0 75 18 D1
e0150 E2 D1 E2 D1 EB E2 F2 B9 08 00 A9 00 C0 75 08 D1
e0160 E0 D1 E0 D1 EB E2 F3 0B DB 74 1B B9 04 00 8B 16
e0170 AB 02 A1 AD 02 F7 F3 33 D2 03 C3 83 D2 00 D1 EA
e0180 D1 D8 8B D8 E2 E8 89 1E B1 02 C3 BA B5 02 52 B4
e0190 0A CD 21 5E 83 C6 02 33 C0 33 C9 83 3E A9 02 01
e01A0 74 33 8A 0C 80 F9 2E 75 0B C7 06 A9 02 01 00 46
e01B0 33 C0 EB E7 80 E9 30 80 F9 09 77 14 BB 0A 00 F7
e01C0 E3 03 C1 83 D2 00 0B D2 75 3E A3 AB 02 46 EB CB
e01D0 A3 AB 02 EB 32 83 3E AF 02 03 7D 18 8A 0C 80 E9
e01E0 30 80 F9 09 77 0E BB 0A 00 F7 E3 03 C1 FF 06 AF
e01F0 02 46 EB A7 8B D0 33 C0 8B 1E AF 02 D1 E3 8B 8F
e0200 A1 02 F7 F1 A3 AD 02 C3 C7 06 B3 02 01 00 C3 BF
e0210 B5 02 FC B9 08 00 B0 20 57 F3 AA 5F C6 45 08 24
e0220 C6 45 04 30 A1 B1 02 8B D0 B1 07 D3 EA B1 09 D3
e0230 E0 BB 0A 00 52 F7 E3 80 C2 30 88 55 06 F7 E3 80
e0240 C2 30 88 55 07 C6 45 05 2E 58 0B C0 74 0D 33 D2
e0250 F7 F3 80 C2 30 88 55 04 4F EB EF BA 8D 02 B4 09
e0260 CD 21 BA B5 02 B4 09 CD 21 C3 63 61 6C 63 20 73
e0270 71 72 74 28 6E 29 2C 28 30 2E 30 30 3C 6E 3C 36
e0280 35 35 33 36 2E 39 39 29 2C 6E 3D 3F 24 0A 24 0A
e0290 49 6E 76 61 6C 69 64 20 69 6E 70 75 74 21 21 21
e02A0 24 01 00 0A 00 64 00 E8 03 00 00 00 00 00 00 00
e02B0 00 00 00 00 00 0C
Areslee 2005-09-05
  • 打赏
  • 举报
回复
回复人: liangbch(宝宝) ( ) 信誉:100 2005-09-04 20:08:00 得分: 0


8086 汇编中,整数的最大范围是65535,楼主的要求是数的范围是0-65535,这样,该数乘以100就超范围了


---------------------------
拜托,除法可以用32位表示。。。。。。
加载更多回复(15)

21,459

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧