To look at using C library functions such as printf and scanf for basic console input/output in Assembly Language.
The quickest and easiest approach to using console I/O in Assembly Language that will be somewhat operating system agnostic, is to use the printf and scanf functions from the standard C library. When writing programs in NASM to use these C library functions, you should include extern directives for the four following functions: printf, scanf, getchar, get_stdout, and fflush. Note: the registers used in 64-Bit Windows ( Win64_regs ) and 64-Bit Linux ( Linux64_regs ) are different! Also note, that for 32-Bit programming, the parameters have to be pushed on to the stack.
1st = rcx
2nd = rdx
3rd = r8
4th = r9
5th = [rsp+20h]
6th = [rsp+28h]
An excellent bit from Calling conventions for different C++ compilers and operating systems, by Agner Fog, Technical University of Denmark, in regards to the shadow space:
The caller must reserve 32 bytes of stack space as "shadow space" for register parameters, even if there are no parameters. The 32 bytes of shadow space come immediately after the return address. Any parameters on the stack come after the 32 empty bytes. The intended purpose of the shadow space is as a "home address" for the register parameters which the called function can use for storing the register parameters in case the registers are used for something else. The caller does not need to put anything into the shadow space. Since the shadow space is owned by the called function, it is safe to use these 32 bytes of shadow space for any purpose by the called function. Even a function without parameters can rely on having 32 bytes of storage space after the return address.
The entire pdf file can be found at: [ calling_conventions.pdf ]
1st = rdi
2nd = rsi
3rd = rdx
4th = rcx
5th = r8
6th = r9
lp: call getchar
cmp al, 0Ah ; is al linefeed (ascii 0Ah)?
jne lp
... ; code to execute after buffer is cleared out
Specifier Output
%c Character
%d or %i Signed decimal integer
%e Scientific notation (mantissa/exponent) using e character
%E Scientific notation (mantissa/exponent) using E character
%f Decimal floating point
%g Use the shorter of %e or %f.
%G Use the shorter of %E or %f
%o Signed octal
%s String of characters
%u Unsigned decimal integer
%x Unsigned hexadecimal integer
%X Unsigned hexadecimal integer (capital letters)
Example in C/C++:
x = 9; y = 6; sum = x + y;
printf("The sum of %d and %d is %d\n", x, y, sum); // Outputs: The sum of 9 and 6 is 15
In Assembly Language:
extern printf
extern get_stdout
extern fflush
section .data
x dq 9
y dq 6
sum dq 0
message db "The sum of %ld and %ld is %ld", 13, 10, 0
section .text
global main
main:
mov rax, [x] ; load value of x into rax
add rax, [y] ; add value of y to rax
mov [sum], rax ; store rax in sum
mov rax, 0 ; clear out rax, if rax is nonzero, then printf will hang looking for floating values in format string
lea rdi, [message] ; rdi points to memory address of format string
mov rsi, [x] ; rsi contains second parameter value
mov rdx, [y] ; rdx contains third parameter value
mov rcx, [sum] ; rcx contains fourth parameter value
call printf ; call printf
call get_stdout ; get_stdout gets the file handle of output stream
mov rdi, rax ; returned in rax, copied to rdi since fflush take one parameter, the handle
call fflush ; flush the output stream (this makes the output window in SASM output right away)
xor eax, eax ; clear out rax for return value
ret
. . . . . . . . . ( end of section Assembly Language Console I/O) <<Contents | Index>>