> i'm new user in nasm and i try to write a simple coding. My aim is to add 2
> number and then print out the sum..but...got syntax error...
> here is the coding that i try..
>
> org 100h
>
> mov ah,9 ;move the number 9 to register
Why "ah"? This looks like part of the "setup" for the "int 21h"... or is it part of the addition? In any case, ax now contains 9xxh, where the "xx" is whatever was in al at program startup. As I recall (and my memory is fuzzy on this), when a .com file starts up, ax contains the number of valid FCBs given on the command line - "probably" zero, but I wouldn't count on it. You probably want "mov ax, 9" here (assuming it's part of the addition).
> add ax,6 ;add the number 6 to same regiater
Now al = 6 + xx... if this comes to more than 255 (unlikely in this case) there will be a carry into ah, so ah is probably still 9, but might be 0Ah...
> mov sum,ax ;move the register to the sum
This is the first syntax error. "sum" is the address/offset of the variable... you're trying to change an immediate value. You want "mov [sum], ax"... the "[]" indicating "contents of memory". This will overwrite the first two bytes of "[sum]" - you seem to only leave one byte in "[sum]" for the result.
> int 21h
With ah = 9, this will attempt to write a "$-terminated" string, pointed to by dx... which is "who-knows-what".
> mov ah,4ch
>
> int 21h
Good!
> sum dh,0Dh,0Ah,'$'
This is another syntax error. I don't know what "dl" is supposed to be... the register? I'm afraid we can't do that. If it's supposed to be a symbol, bad name... since it's a register...
What you want here (perhaps) is the $-terminated string, but with sufficient space to write the result - expressed as ascii characters, *not* just stuff the number in there!
In the simplest case, the result can be expressed as a single decimal digit...
mov al, 2
add al, 3
mov [sum], al
now "sum" looks like:
5, 0Dh, 0Ah, '$'
Printing this won't give the result you want - the number 5 is *not* the ascii character '5' - we need to add 30h or 48 or '0' to get the ascii decimal digits...
mov al, 2
add al, 3
add al, '0'
mov [sum], al
Now you'd print "5". Okay for a single digit, but if the result is 10, we need to print '1', then '0' - obviously, there's no ascii code for "10". Since ax (if that's what you want to use) will hold values from 0 to 65535, "sum" should leave space for 5 possible digits. You need to decide how large a number you want to be able to handle - the example I gave with "al" will only handle numbers from 0 to 255 - if the result is larger than 255, this simple example will silently print incorrect results! (pretty bad "bug"!) The easy fix is:
mov al, 200
add al, 60
jc overflow
add al, '0'
mov [sum], al
...
overflow:
; do something about it
If you use a 16-bit register, like ax, you can go to 65535, if you use eax, you can go to 4 billion and change - but there's *still* the possibility of an overflow, and you should still check for it!
You could also use a larger register (and/or memory location) for the "result" than for the inputs.
> what wrong with my coding??
Besides the syntax errors, you may not have thought through what you want to do...
> need help and pls show me the correct coding..
There's no single "correct" way to do it. In order to isolate the decimal digits you need to print, the "div" instruction can be useful - if you "div" by a word, the quotient is in ax, the remainder is in dx... the remainder(s) will give us the decimal digits, but in the opposite order from how we want to print them (and '0' has to be added to get an ascii character). One way to do it...
org 100h
mov ax, 9
add ax, 6
; jc overflow ; - won't happen for these inputs
mov bx, 10
mov di, sum + 4
top:
xor dx, dx
div bx
add dl, '0'
mov [di], dl
or ax, ax
jz done
dec di
jmp top
done:
mov ah, 9
mov dx, di
int 21h
; exit cleanly
sum db 0, 0, 0, 0, 0, 0Dh, 0Ah, '$'
That's untested and may have errors. Here's a slightly different way (it adds three digits, but you can figure out how to cut it down to two, I'm sure). This one *does* seem to work. It isn't intended to be the "best" method, but it's fairly easy to understand, I think.
Best,
Frank
; adds three values and prints result as decimal, hex, and binary
; nasm -f bin -o add3.com add3.asm
org 100h
section .data
A dw 1
B dw 2
C dw 3
overflow_msg db "Overflow!", 10, 13, '$'
section .text
mov ax, [A]
add ax,
jc overflow
add ax, [C]
jc overflow
call ax2dec
call newline
call ax2hex
call newline
call ax2bin
jmp exit
overflow:
mov ah, 9
mov dx, overflow_msg
int 21h
exit:
mov ah, 4Ch
int 21h
;--------------
;--------------
ax2dec:
push ax
push bx
push cx
push dx
mov bx, 10 ; divide by ten
xor cx, cx ; zero our counter
.push_digit:
xor dx, dx ; clear dx for the div
div bx ; dx:ax/bx -> ax quotient, dx remainder
push dx ; save remainder
inc cx ; bump digit counter
or ax, ax ; is quotient zero?
jnz .push_digit ; no, do more
mov ah, 2 ; print character subfunction
.pop_digit:
pop dx ; get remainder back
add dl, '0' ; convert to ascii character
int 21h ; print it
loop .pop_digit ; cx times
pop dx
pop cx
pop bx
pop ax
ret
;-------------------
;-------------------
ax2hex:
push cx
push dx
mov cx, 4 ; four digits to show
.top
rol ax, 4 ; rotate one digit into position
mov dl, al ; make a copy to process
and dl, 0Fh ; mask off a single (hex) digit
cmp dl, 9 ; is it in the 'A' to 'F' range?
jbe .dec_dig ; no, skip it
add dl, 7 ; adjust
.dec_dig:
add dl, 30h ; convert to character
push ax
mov ah, 2 ; print the character
int 21h
pop ax
loop .top
pop dx
pop cx
ret
;--------------------------
;--------------------------
ax2bin:
push cx
push dx
mov cx, 16
.top
rcl ax, 1 ; rotate and set/clear carry
mov dl, '0'
adc dl, 0 ; make it '1' if carry set
push ax
mov ah, 2 ; print it
int 21h
pop ax
loop .top
pop dx
pop cx
ret
;----------------------------
;----------------------------
newline:
push ax
push dx
mov ah, 2 ; print character in dl
mov dl, 13 ; carriage return
int 21h
mov dl, 10 ; and linefeed
int 21h
pop dx
pop ax
ret
;----------------------------