Author Topic: print error messages (using C definitions...)  (Read 16089 times)

nobody

  • Guest
print error messages (using C definitions...)
« on: February 29, 2008, 01:29:19 PM »
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)

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

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 :)
; 32 because i did 32-bytes message strings
   lea dword esi, [errno_table + eax]
   call WriteMsg   ; prints a zero-terminated string
   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

AC

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: print error messages (using C definitions...)
« Reply #1 on: February 29, 2008, 04:57:55 PM »
> 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

nobody

  • Guest
Re: print error messages (using C definitions...)
« Reply #2 on: March 01, 2008, 12:18:38 AM »
Couldn't resist trying "call open" instead of int 80h... Getting ": No such file or directory". Closer... But less and less "assembly language"...

Best,
Frank

nobody

  • Guest
Re: print error messages (using C definitions...)
« Reply #3 on: March 01, 2008, 12:24:18 AM »
hell, this forum is cutting spaces in the posts...so, you couldn't see that the messages were 30 bytes long ^^

> shl eax, 5 ?

tricky ! but less understandable at first sight :)

there's definitely not enough information about how C functions work. what is possible with C is also possible with asm. i don't know how perror works at all

this is a program that works:
SECTION .text

extern printf                  

global main

message  db "Number to print : %d",10,0   

main:

push dword 0x500

push dword message

call printf

add esp,8
--------------------------------
(output)
Number to print : 1280

it tells us that the parameters are pushed in reverse order... but that's all.
with "perror" we're dealing with this famous errno

"  errno is defined by the ISO C standard to be  a  modifiable  lvalue  of
        type  int,  and  must not be explicitly declared; errno may be a macro.
        errno is thread-local; setting it in one thread  does  not  affect  its
        value in any other thread. "

curious enough, perror alone will give "Success", and a second perror (on the next line of later) will give "Invalid seek"

well...i'm giving up too
---------------------------------
%ifdef DEBUG
; the "good" macro
%else
; the shorter way - "jmp exit"
%endif

i like that. pretty convenient actually

i finished this errno-base.inc, équivalent of /usr/include/asm-generic/errno-base.h, and the program i'm working on actually use it when i don't specify a correct file path,
i get "No such file or directory"
yeah!