> how is it possible to use gcc linker instead of ld in order to have the error
> message corresponding to ERRNO printed after a int 80h call?
> (i.e. be able to use the perror() function)
Damned if I know, AC. I've tried this:
global main
extern perror
section .text
main:
xor ecx, ecx
mov ebx, nsf
mov eax, 5
int 80h
cmp eax, -4096
jc exit
; neg eax
; push eax
call perror
; add esp, 4
exit:
mov eax, 1
int 80h
section .data
nsf db "nothere.xyz", 0
Compiles quietly, now how do I *use* perror??? Take a parameter? Void? (must know about "errno"?) With the "push eax" in, it segfaults. Without it, it prints some garbage, followed by the word "Success" (!!!). I take this as a good sign, but I can't get it to print a message. We may need to call "write()" instead of the int 80h interface to make this work(?). Someone who knows more C can fool with it - I'm gonna quit while I'm ahead. :)
> when i include in a C code, it doesn't seem to make the file bigger,
> but in asm i didn't find a way to do something similar
When you link in more functions, they're in a shared library, so don't add much to the preexisting bloat. We could put our "asm_perror" in a shared library, too, but that's trickier. Not much point, since we'll probably be the only ones using it. (the solution to this is to run more asm programs!)
> in put in my code
> %include 'errno.inc'
>
> and a function looking like this:
> Errno:
> neg eax ; eax is signed after call failure
> dec eax
> imul eax, 32 ; "imul", signed multiplication, because i couldn't get "mul"
> to work :)
shl eax, 5 ?
> ; 32 because i did 32-bytes message strings
> lea dword esi, [errno_table + eax]
> call WriteMsg ; prints a zero-terminated string
To stdout or stderr?
> ret
>
> with the include file looking like this:
> errno_table db 'Operation not permitted ', 10, 0 ; EPERM
> db 'No such file or directory ', 10, 0 ; ENOENT
> [etc...]
> but, this does make my file grow in size, because it's not %define 's or anything,
> as i understand
Makes your file grow in size because you're doing more! I'm against "bloat", but this is "functionallity"!
I've got a "work in progress" (okay, "progress" is optimistic) to do the same thing. I take a slightly different approach, strings of variable length, and a second table of addresses, in which I look up which string to print... Has the advantage that it allows longer strings, if desired, but is more complicated - particulary more complicated to modify into a shared library. I may revert to your method of fixed-length strings... (another option would be to "count zeros" in a block of zero-terminated strings - variable length, to find the one we want. Dog slow, on the face of it, but it isn't *that* big a block of text to walk through, and we're not doing it too often... are we???)
I propose to call this by a macro, like:
...
int 80h
checkerror "we were doing this", exit
which will print the text, so we know where the error happened, print the error message, like you're doing, and jump to the "exit" label (which we assume exists). Won't always be "exit" - we might want to let the user "guess again"... (if eax is < 0FFFFF000h it falls through, of course) For *some* functions, we can get a "negative" value which is valid - memory functions, or perhaps with O_LARGEFILE... for a generic "asm_perror", we ought to do it right, although just "js" is shorter and will work for "most" cases - I still use just "js" ("jns" usually), but it's "slopppy".
If we want to create a smaller "release" version or a "debug" version, we can:
%ifdef DEBUG
; the "good" macro
%else
; the shorter way - "jmp exit"
%endif
%ifdef DEBUG
; our "good" asm_perror
; with all the text
%include "errno.inc", I suppose...
%else
; the shorter way - perhaps nothing
%endif
We can assemble to asm_perror.o, and optionally link against that, as well as the "%include" method. Programmer's choice!
Best,
Frank