| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1523 人关注过本帖
标题:[求助]兩數相加程式
只看楼主 加入收藏
andrew9
Rank: 1
等 级:新手上路
帖 子:6
专家分:0
注 册:2006-12-12
结帖率:100%
收藏
 问题点数:0 回复次数:6 
[求助]兩數相加程式
由於小弟我是初學Assembly Language,老師上課要我們交一個作業,如題:寫一NASM程式,可以輸入兩個數字,計算加總之後輸出結果。要求:輸入x.y兩數,範圍在-128~127之間計算z=x+y 輸出時同時輸出x.y.z之二進、八進、十六進避免用課本之macro!

可是我能力不足,只會最基本印出字串
不知道高手能否幫小弟完成老師要的作業呢:-(
以下是小弟寫的一部分

ORG 0100H
JMP start
msg DB 'please keyin the first integer : ', '$'
msg2 DB 'please keyin the second integer :', '$'
newline DB 13, 10, '$'
x DB 7
y DB -5
z DB 0
msg3 DB 'z=x+y= '
total DB ' ', 13, 10, '$'

start: MOV DX, msg
MOV AH, 09H
INT 21H
MOV DX, newline
MOV AH, 09H
INT 21H


MOV DX, msg2
MOV AH, 09H
INT 21H
MOV DX, newline
MOV AH, 09H
INT 21H

MOV AL, [x]
ADD AL, [y]
MOV [z], AL
MOV DX, msg3
MOV AH, 09H
INT 21H

MOV AX, 4c00H
INT 21H
搜索更多相关主题的帖子: 程式 相加 
2006-12-12 01:08
菜鸟上路
Rank: 4
等 级:贵宾
威 望:14
帖 子:1120
专家分:0
注 册:2006-3-21
收藏
得分:0 
搜索此版块,以前有过这样的帖子

2006-12-12 10:14
andrew9
Rank: 1
等 级:新手上路
帖 子:6
专家分:0
注 册:2006-12-12
收藏
得分:0 
我有搜索過阿,可是我們用的是nasm的組譯器,很多地方我都看不懂耶
2006-12-12 12:49
公子吕
Rank: 1
等 级:新手上路
帖 子:79
专家分:0
注 册:2006-5-4
收藏
得分:0 

代码在masm5下测试通过,只能进行-127~~128之间的加法且结果不能超出-127~~128 这是因为受到程序里面那两个过程(itoaproc & atoiproc)的限制。
下班了来不及写注释和详细解释,明天来补充!


data segment
msg DB 'please keyin the first integer : ', '$'
msg2 DB 'please keyin the second integer :', '$'
msg3 DB 'x+y='
out_buffer db 4 dup(?)
db '$','$'
newline DB 13, 10, '$'

first_number db 4
db ?
db 2 dup(?)
second_number db 4
db ?
db 2 dup(?)

data ends

code segment
assume cs:code,ds:data

start:
mov ax,data
mov ds,ax
xor ax,ax
MOV AH, 09H
MOV DX, offset msg
INT 21H
mov dx,offset first_number
mov ah,10
int 21h
add dx,2
mov bx,dx
push bx
call atoiproc
xor cx,cx
mov cx,ax
MOV DX, offset newline
MOV AH, 09H
INT 21H


MOV DX, offset msg2
MOV AH, 09H
INT 21H
mov dx,offset second_number
mov ah,10
int 21h
add dx,2
mov bx,dx
push bx
call atoiproc
add ax,cx

mov bx,offset out_buffer
push ax
push bx
call itoaproc

MOV DX, offset newline
MOV AH, 09H
INT 21H

mov dx,offset msg3
mov ah,9
int 21h

mov ah,7
int 21h
mov ah,4ch
int 21h

;;--------------------------------------------------------------------------
atoiproc proc near
push bp ; save base pointer
mov bp, sp ; establish stack frame
sub sp, 2 ; local space for sign
push bx ; Save registers
push cx
push dx
pushf ; save flags

mov si,[bp+4] ; get parameter (source addr)

WhileBlank: cmp BYTE PTR [si],' ' ; space?
jne EndWhileBlank ; exit if not
inc si ; increment character pointer
jmp WhileBlank ; and try again
EndWhileBlank:

mov ax,1 ; default sign multiplier
IfPlus: cmp BYTE PTR [si],'+' ; leading + ?
je SkipSign ; if so, skip over
IfMinus: cmp BYTE PTR [si],'-' ; leading - ?
jne EndIfSign ; if not, save default +
mov ax,-1 ; -1 for minus sign
SkipSign: inc si ; move past sign
EndIfSign:

mov [bp-1],ax ; save sign multiplier
mov ax,0 ; number being accumulated
mov cx,0 ; count of digits so far

WhileDigit: cmp BYTE PTR [si],'0' ; compare next character to '0'
jl EndWhileDigit ; not a digit if smaller than '0'
cmp BYTE PTR [si],'9' ; compare to '9'
jg EndWhileDigit ; not a digit if bigger than '9'
mov dl,10
imul dl ; multiply old number by 10
jo overflow ; exit if product too large
mov bl,[si] ; ASCII character to BL
and bx,000Fh ; convert to single-digit integer
add ax,bx ; add to sum
jc overflow ; exit if sum too large
inc cx ; increment digit count
inc si ; increment character pointer
jmp WhileDigit ; go try next character
EndWhileDigit:

cmp cx,0 ; no digits?
jz overflow ; if so, set overflow error flag

; if value is 8000h and sign is '-', want to return 8000h (-32,768)

cmp ax,8000h ; 8000h ?
jne TooBig?
cmp WORD PTR [bp-1],-1 ; multiplier -1 ?
je ok1 ; if so, return 8000h

TooBig?: test ax,ax ; check sign flag
jns ok ; will be set if number > 32,767

overflow: pop ax ; get flags
or ax,0000100001000100B ; set overflow, zero & parity flags
and ax,1111111101111110B ; reset sign and carry flags
push ax ; push new flag values
mov ax,0 ; return value of zero
jmp AToIExit ; quit

ok: imul WORD PTR [bp-1] ; make signed number
ok1: popf ; get original flags
test ax,ax ; set flags for new number
pushf ; save flags

AToIExit: popf ; get flags
pop dx ; restore registers
pop cx
pop bx
mov sp, bp ; delete local variable space
pop bp
ret 2 ; exit, removing parameter
atoiproc ENDP

;;------------------------------------------------------------------------
itoaproc proc near
push bp
mov bp,sp
push ax
push bx
push cx
push dx
push di
pushf

mov ax,[bp+6]
mov di,[bp+4]

ifSpecial:
cmp ax,8000h
jne EndIfSpecial
mov BYTE PTR [di],'-'
mov BYTE PTR [di+1],'3'
mov BYTE PTR [di+2],'2'
mov BYTE PTR [di+3],'7'
mov BYTE PTR [di+4],'6'
mov BYTE PTR [di+5],'8'
jmp ExitIToA
EndIfSpecial:

mov dx, ax

mov al,' '
mov cx,5 ; first five
cld ; bytes of
rep stosb ; destination field

mov ax, dx ; copy source number
mov cl,' ' ; default sign (blank for +)
IfNeg: cmp ax,0 ; check sign of number
jge EndIfNeg ; skip if not negative
mov cl,'-' ; sign for negative number
neg ax ; number in AX now >= 0
EndIfNeg:

mov bx,10 ; divisor

WhileMore: mov dx,0 ; extend number to doubleword
div bx ; divide by 10
add dl,30h ; convert remainder to character
mov [di],dl ; put character in string
dec di ; move forward to next position
cmp ax,0 ; check quotient
jnz WhileMore ; continue if quotient not zero

mov [di],cl ; insert blank or "-" for sign

ExitIToA: popf ; restore flags and registers
pop di
pop dx
pop cx
pop bx
pop ax
pop bp
ret 3 ;exit, discarding parameters
itoaproc endp
;;---------------------------------------------------------------------------


code ends
end start

2006-12-12 18:04
菜鸟上路
Rank: 4
等 级:贵宾
威 望:14
帖 子:1120
专家分:0
注 册:2006-3-21
收藏
得分:0 
以下是引用公子吕在2006-12-12 18:04:56的发言:

代码在masm5下测试通过,只能进行-127~~128之间的加法且结果不能超出-127~~128 这是因为受到程序里面那两个过程(itoaproc & atoiproc)的限制。
下班了来不及写注释和详细解释,明天来补充!


data segment
msg DB 'please keyin the first integer : ', '$'
msg2 DB 'please keyin the second integer :', '$'
msg3 DB 'x+y='
out_buffer db 4 dup(?)
db '$','$'
newline DB 13, 10, '$'

first_number db 4
db ?
db 2 dup(?)
second_number db 4
db ?
db 2 dup(?)

data ends

code segment
assume cs:code,ds:data

start:
mov ax,data
mov ds,ax
xor ax,ax
MOV AH, 09H
MOV DX, offset msg
INT 21H
mov dx,offset first_number
mov ah,10
int 21h
add dx,2
mov bx,dx
push bx
call atoiproc
xor cx,cx
mov cx,ax
MOV DX, offset newline
MOV AH, 09H
INT 21H


MOV DX, offset msg2
MOV AH, 09H
INT 21H
mov dx,offset second_number
mov ah,10
int 21h
add dx,2
mov bx,dx
push bx
call atoiproc
add ax,cx

mov bx,offset out_buffer
push ax
push bx
call itoaproc

MOV DX, offset newline
MOV AH, 09H
INT 21H

mov dx,offset msg3
mov ah,9
int 21h

mov ah,7
int 21h
mov ah,4ch
int 21h

;;--------------------------------------------------------------------------
atoiproc proc near
push bp ; save base pointer
mov bp, sp ; establish stack frame
sub sp, 2 ; local space for sign
push bx ; Save registers
push cx
push dx
pushf ; save flags

mov si,[bp+4] ; get parameter (source addr)

WhileBlank: cmp BYTE PTR [si],' ' ; space?
jne EndWhileBlank ; exit if not
inc si ; increment character pointer
jmp WhileBlank ; and try again
EndWhileBlank:

mov ax,1 ; default sign multiplier
IfPlus: cmp BYTE PTR [si],'+' ; leading + ?
je SkipSign ; if so, skip over
IfMinus: cmp BYTE PTR [si],'-' ; leading - ?
jne EndIfSign ; if not, save default +
mov ax,-1 ; -1 for minus sign
SkipSign: inc si ; move past sign
EndIfSign:

mov [bp-1],ax ; save sign multiplier
mov ax,0 ; number being accumulated
mov cx,0 ; count of digits so far

WhileDigit: cmp BYTE PTR [si],'0' ; compare next character to '0'
jl EndWhileDigit ; not a digit if smaller than '0'
cmp BYTE PTR [si],'9' ; compare to '9'
jg EndWhileDigit ; not a digit if bigger than '9'
mov dl,10
imul dl ; multiply old number by 10
jo overflow ; exit if product too large
mov bl,[si] ; ASCII character to BL
and bx,000Fh ; convert to single-digit integer
add ax,bx ; add to sum
jc overflow ; exit if sum too large
inc cx ; increment digit count
inc si ; increment character pointer
jmp WhileDigit ; go try next character
EndWhileDigit:

cmp cx,0 ; no digits?
jz overflow ; if so, set overflow error flag

; if value is 8000h and sign is '-', want to return 8000h (-32,768)

cmp ax,8000h ; 8000h ?
jne TooBig?
cmp WORD PTR [bp-1],-1 ; multiplier -1 ?
je ok1 ; if so, return 8000h

TooBig?: test ax,ax ; check sign flag
jns ok ; will be set if number > 32,767

overflow: pop ax ; get flags
or ax,0000100001000100B ; set overflow, zero & parity flags
and ax,1111111101111110B ; reset sign and carry flags
push ax ; push new flag values
mov ax,0 ; return value of zero
jmp AToIExit ; quit

ok: imul WORD PTR [bp-1] ; make signed number
ok1: popf ; get original flags
test ax,ax ; set flags for new number
pushf ; save flags

AToIExit: popf ; get flags
pop dx ; restore registers
pop cx
pop bx
mov sp, bp ; delete local variable space
pop bp
ret 2 ; exit, removing parameter
atoiproc ENDP

;;------------------------------------------------------------------------
itoaproc proc near
push bp
mov bp,sp
push ax
push bx
push cx
push dx
push di
pushf

mov ax,[bp+6]
mov di,[bp+4]

ifSpecial:
cmp ax,8000h
jne EndIfSpecial
mov BYTE PTR [di],'-'
mov BYTE PTR [di+1],'3'
mov BYTE PTR [di+2],'2'
mov BYTE PTR [di+3],'7'
mov BYTE PTR [di+4],'6'
mov BYTE PTR [di+5],'8'
jmp ExitIToA
EndIfSpecial:

mov dx, ax

mov al,' '
mov cx,5 ; first five
cld ; bytes of
rep stosb ; destination field

mov ax, dx ; copy source number
mov cl,' ' ; default sign (blank for +)
IfNeg: cmp ax,0 ; check sign of number
jge EndIfNeg ; skip if not negative
mov cl,'-' ; sign for negative number
neg ax ; number in AX now >= 0
EndIfNeg:

mov bx,10 ; divisor

WhileMore: mov dx,0 ; extend number to doubleword
div bx ; divide by 10
add dl,30h ; convert remainder to character
mov [di],dl ; put character in string
dec di ; move forward to next position
cmp ax,0 ; check quotient
jnz WhileMore ; continue if quotient not zero

mov [di],cl ; insert blank or "-" for sign

ExitIToA: popf ; restore flags and registers
pop di
pop dx
pop cx
pop bx
pop ax
pop bp
ret 3 ;exit, discarding parameters
itoaproc endp
;;---------------------------------------------------------------------------


code ends
end start

,不过我觉得好象显得麻烦了


2006-12-12 18:33
andrew9
Rank: 1
等 级:新手上路
帖 子:6
专家分:0
注 册:2006-12-12
收藏
得分:0 
請問一下喔,我現在已經修改成這樣,不過只能輸入一個字元,來進行相加,請問我要如何在修改才能變成 -127~128的範圍相加呢

ORG 0100H
JMP start
msg DB 'please keyin the first integer : ', 13, 10,'$'

msg2 DB 'please keyin the second integer :', 13, 10, '$'

x DB ' '
y DB ' '
newline DB 13, 10, '$'
msg3 DB 'z=x+y= '
z DB ' ', '$'

start: MOV DX, msg
MOV AH, 09H
INT 21H

MOV AH, 01H
INT 21H
MOV [x], AL
MOV DX, newline
MOV AH, 09H
INT 21H

MOV DX, msg2
MOV AH, 09H
INT 21H
MOV AH, 01H
INT 21H
MOV [y], AL

ADD AL, [x]
DAA

SUB AL, 30H

MOV [z], AL
MOV DX, msg3
MOV AH, 09H
INT 21H
MOV DX, newline
MOV AH, 09H
INT 21H

MOV DX, newline
MOV AH, 09H
INT 21H

MOV AX, 4c00H
INT 21H
2006-12-12 18:48
公子吕
Rank: 1
等 级:新手上路
帖 子:79
专家分:0
注 册:2006-5-4
收藏
得分:0 
嘿嘿。。。菜鸟上路 大侠说的是,上次有个“输入十进制转换十六进制输出”的程序,输入输出处理的都非常简单。值得学习。不过我已经习惯地在程序里用宏调用那两个过程了(懒阿,不想动脑子,惭愧一下)下面是<十进制输入十六进制输出>的链接http://bbs.bc-cn.net/dispbbs.asp?boardid=126&replyid=406132&id=107323&page=1&skin=0&Star=1楼主可以参考。。
解释一下上面那两个过程的用法:itoaproc将整数转换成数字串,调用前将保存数字串的地址送bx,要转换的数送ax,将ax,bx先后压入堆栈,调用后数字串被保存在bx指向的地址中。 atoiproc将数字串转换成整数,调用前将数字串送bx,调用后转换的数字被保存在ax中。
楼主的这几行代码我有些疑问:
MOV DX, newline ;dx中存放输出字符串的地址,应该是LEA DX,newline 或
MOV AH, 09H ;MOV DX,OFFSET newline 吧。没用过nasm 不知道是不是这样。。。
INT 21H
2006-12-12 21:55
快速回复:[求助]兩數相加程式
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.025479 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved