I was writing a simple NASM x64 Assembly program that adds two single-digit numbers(4
and 5
respectively) and print it on the screen. However, I wanted to use a procedure call(function). So I designed the the program in C language first.
#include <stdio.h>
int sum(int x, int y) {
int result = x + y;
return result;
}
int main(void) {
int x = 4;
int y = 5;
int result = sum(x, y);
printf("The sum is: %d\n", result);
return 0;
}
And I rewrote the program in NASM x64 Assembly program like below. The expected output from the program was The sum is: 9
. However, I only could see the result except for the calculation result, just The sum is:
.
; Nasm 2.15.05 (on Linux x64)
STDOUT equ 0x01 ; for RDI (file descriptor)
WRITE equ 0x01 ; for RAX (for syscall itself)
section .data
message db "The sum is: "
messageLength equ $ - message
section .text
global _start
_start:
mov rax, WRITE
mov rdi, STDOUT
mov rsi, message
mov rdx, messageLength
syscall
mov rdi, 0x4
mov rsi, 0x5
call _sum
mov rcx, rax ; The result of the _sum (stored in RAX register)
mov rax, WRITE
mov rdi, STDOUT
mov rsi, rcx
mov rdx, 0x01
syscall
; exit
mov rax, 0x3C
mov rdi, 0x00
syscall
_sum:
mov rax, rdi
add rax, rsi
add rax, '0' ; To make it printable ASCII
ret ; Result: 0x39 (A single character '9' in ASCII)
(My environment is WSL Ubuntu 22.04 on Windows 11, Intel i9-13900H CPU)
knightchaser@3rdfr13nds:~/assembly$ ./procedures_x64
The sum is: knightchaser@3rdfr13nds:~/assembly$
With GDB(GNU Debugger), I checked the calculation of _sum
was successful so 0x39
(9
in ASCII character) was stored in RAX
register and the program doesn't show any explicit errors like segmentation fault
.
I used the following commands to make the executable program.
nasm -f elf64 -o procedures_x64.o procedures_x64.asm
ld -o procedures_x64 procedures_x64.o
But I can't see the result. Are there wrong points in my Assembly code? Thanks in advance!
To print your character you do
mov rcx, rax ; The result of the _sum (stored in RAX register)
;...
mov rsi, rcx
The problem is that the value returned in rax
is a single character, and you move that single character value into rsi
. The write
system call expects the value in rsi
to be a pointer to a character, not the actual character value itself.
You need to store the character in memory, and then pass a pointer to that memory to the write
function.
If you wrote an exact equivalent in C it would be very obvious when you have to use the pointer-to operator &
to print the returned character (or used a character array). I highly recommend that you get the proper C Program working, with the system calls and a proper sum
function and conversion from int
to a string, and use that as the blueprint for the assembly program.