Hello everyone!
Not so long ago I decided to learn assembly language. I have grasped the basics of it more or less, but there is one problem that I cannot solve (and find any help about). I wrote a program to output the sum of two integers that are entered by the user. I'm using the kernel sys_call write. It seems to add them up correctly, but it prints out the ASCII symbol of that number (or similar)! I've tried YASM, FASM and NASM, but the result is the same. Can anyone give me some advice as to how to output the actual number, not the ASCII code? Here's the source code -

....
section .bss
                  input1 resd 1
	input2 resd 1
	sum     resd 1
section .text
    global _start
    _start:
....
	mov	rax,[input1]
	add	rax,[input2]
	mov	[sum], rax

	; print sum
                mov           rdx,2
                lea             rcx,[sum]
                mov           rbx, 1
                mov           rax,4
                int 0x80

Please help or give some advice as to how I can get rid of this! Without solving this problem I cannot continue any further.

Recommended Answers

All 10 Replies

what you are doing is attempting to print the binary value of the number. It has to be converted to ASCII before it can be printed. If you look at an ascii chart you will see that the ascii value for '0' is 48 decimal, or 30H. So if you want to print the 0 digit you have to add 48 to make it printable on the screen.

using a loop your program needs to split the value of sum up into its individual digits and add 30H to the digit before printing it.

Thanks a lot for your reply. I will try it out soon, at least for singel digits. Is there a simpler way of fixing it?

If your application is pure assembly then the way AncientDragon explained it is the only way unless you use BCD or want to display result in decimal. A lot of applications I do are for windows therefore I use wsprintf a function of kernel32.lib and then one of the parameters such as %d or decimal or %X for hex will do the conversion for me

Guess I'll just have to try it then. Thanks a lot anyway!

If you really get stuck I can post a short snippet on the example Ancient Dragon gave you. Just to clarify you are using NASM on an intel based machine that uses Linux. The reason I ask is that I'm assuming in your first post rax actually means eax.

I'll be away for a bit so I'll give you the snippet regardless. This is written for an XP based machine, but I'm sure you'll be able to improvise.

push edi
mov al,30H ; Ascii equivalent to "0"
mov edx, 913387 ; You can make this any value
std ; set EDI to auto decrement
mov edi, 401087
.D0 mov al, dl
and al, 15 ; strip bits 7 - 4
or al, 30H
stosb
shr edx, 4 ; shift next digit
jnz .D0
mov eax, edi
inc eax
pop edi
cld
pop edi

This method leaves base address of string in EAX, but you can put it anywhere.

This only works if you are displaying decimal digits. You'll have to modify loop if you want hex in order to display A - F.

Thanks a lot! I managed to do it for one digit, but couldnt think how to do it for two or more! The machine that I'm using is AMD64 bit, so the register rax is equvalent to eax, but just is 64 bit. The assembler is YASM, which fully supports NASM's syntax. Thank you!

I managed to do it for one digit, but couldnt think how to do it for two or more!

I got the same problem. I managed to do it for one digit, but it's just impossible to do it for more.
I'm getting mad about this ><
^^

I'm using MASM32,but with a 16bit Linker.

Can anybody please give me a hint, what i made wrong ?

This is my source code.

DUDU SEGMENT

Affe db "Hallo Das einzige was das Programm hier tut, ist so eine Zeile auszugeben(derzeit nicht ;-))"
db "$"

Fenster db ?

db "$"

DUDU ENDS

TAM SEGMENT

ASSUME CS:TAM,DS:DUDU

Anfang: mov ax,DUDU
mov ds,ax


mov Fenster,85

lea di,Fenster


add Fenster,48

inc di

add Fenster,48


lea dx,Fenster



mov ah,09

int 21h



mov ah,4Ch

int 21h

TAM ENDS

END Anfang

#1: When you move 85 55H into Fenster your result will be two ascii digits. What you've done is added 48 to 85 and then 48 to your terminator $. This might help you out

Fenster     db    85, 0, '$'

mov   dx, offset Fenster
mov   ax, Fenster
push   ax
and    ax, 15
add    ax, 48
mov   dx, al
inc     dx
pop    ax
shr     ax, 4
add    ax, 48
mov    dx, al
dec     dx

I'm not advicating this is the best way to do it, but based on your logic this is probably the closest approximation based on your code

#1: When you move 85 55H into Fenster your result will be two ascii digits. What you've done is added 48 to 85 and then 48 to your terminator $. This might help you out

Fenster     db    85, 0, '$'

mov   dx, offset Fenster
mov   ax, Fenster
push   ax
and    ax, 15
add    ax, 48
mov   dx, al
inc     dx
pop    ax
shr     ax, 4
add    ax, 48
mov    dx, al
dec     dx

I'm not advicating this is the best way to do it, but based on your logic this is probably the closest approximation based on your code

Thanks.
Unfortunately I don't really understand, what you did :-)
But I'll play around with it a bit.

The main purpose of this script is getting a number, stored in ax, getting displayed.

It should be the final part of a calculator. Therefore the actual number in ax should naturally not be important, it should be exchangeable.

Mabye now you understand better, what i suppose the program to do.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.