NASM - The Netwide Assembler
NASM Forum => Using NASM => Topic started by: MrCBofBCinTX on July 13, 2010, 09:45:34 PM
-
Looking around, I finally found something that explains a little about linking asm to C. (found something here which led to a bigger page elsewhere)
I found this (after adapting to Nasm):
#include <stdio.h>
int maxofthree(int, int, int);
int main() {
printf("%d\n", maxofthree(1, -4, -7));
printf("%d\n", maxofthree(2, -6, 1));
printf("%d\n", maxofthree(2, 3, 1));
printf("%d\n", maxofthree(-2, 4, 3));
printf("%d\n", maxofthree(2, -6, 5));
printf("%d\n", maxofthree(2, 4, 6));
return 0;
}
and
global maxofthree
section .text
maxofthree:
mov eax, [esp+4]
mov ecx, [esp+8]
mov edx, [esp+12]
cmp eax, ecx
cmovl eax, ecx
cmp eax, edx
cmovl eax, edx
ret
Which makes sense to me.
But this one works but I don't understand the message: part
$ cat helloworld.asm
; ----------------------------------------------------------------------------
; helloworld.asm
;
; This is a Win32 console program that writes "Hello, World" on one line and
; then exits. It needs to be linked with a C library.
; ----------------------------------------------------------------------------
global main
extern printf
section .text
main:
push message
call printf
add esp, 4
ret
message:
db 'Hello, World', 10, 0
Is the message part proper syntax for Nasm? It seems to lack a name.
I saw several other examples with a data part like that
-
I'm still curious if there is a problem with the above code, even though it works fine.
But I see that following regular Nasm style definitely works fine
-
Yeah... a "label", like "main", and a "variable name", like "message", are actually the same thing - just the address of the next byte. Either can go on the same line, or on the preceeding line by itself. The colon is optional, in either case. Nasm will "warn" about "label alone on a line without a colon", but it still assembles your code. This is a "suppressible warning", and was turned off by default in earlier versions... but if you intend "lodsb" and write "lodbs", Nasm would take the latter as a label, and the intended instruction would just "disappear" without warning. So in recent versions, it's turned on by default. Sort of a half-baked spell checker. :)
I prefer variable names on the same line, without a colon, and labels on a separate line with a colon, but it's just a matter of style. You can mix-and-match as you wish. Older Nasm code may generate a "label alone on a line" warning - some people did it like that. You can ignore the warning, or turn it off, or add the colon. Programmer's choice!
Since you're linking with C, you might want to know about another fairly new feature. If you enclose your text with "back apostrophes" (back-ticks, back quotes) instead of the usual single or double quotes, Nasm will accept "\n" and the other standard C "escapes".
message db `Hello World!\n`, 0
Another "tip" you might run into: printf always expects "floats" (%f) to be doubles (qword), even if they're declared as "float" (dword). This can result in some strange numbers - and other troubles - if you don't know about it! :)
; nasm -f elf hwfloat.asm
; gcc hwfloat.o -o hwfloat
; ./hwfloat
; echo $? to see "answer"
global main
extern printf
section .data
hello_string db 'Hello, World!', 0
the_int dd 42
the_float dd 42.0 ; single precision
format_string db 'The string is "%s"', 10
db 'The float is: %f', 10
db 'The int is: %d', 10, 0
section .text
main:
; printf("the string is %s\nthe float is: %f\n the int is: %d",
; hello_string, the_float, the_int);
;
; push rightmost parameter first...
push dword [the_int]
; printf quietly promotes floats to doubles(!)
; so we'll want 8 bytes on the stack
sub esp, 8
; now put our float there, as double
fld dword [the_float]
fstp qword [esp]
; and the leftmost parameter...
push hello_string
; and the format string last
push format_string
call printf
add esp, 4 * 3 + 8
; "main" returns int (right???)
; zero is the usual "no error" exitcode, but
; return something "identifiable", just for fun
mov eax, 42
ret
We could also do it - if the "float" were declared as double-precision - in two pushes:
section .data
my_double dq 42.0
format_string db `Answer: %f\n', 0
section .text
push dword [my_double + 4]
push dword [my_double]
push format_string
call printf
add esp, 12
(note that the decimal point tells Nasm we want a "float" not an integer)
Nasm is very flexible, and getting better all the time! :)
Best,
Frank
-
Thanks, and the two bonus answers are great to know.
I saw some float examples that didn't work right, I will look over them again.