flat assembler
Message board for the users of flat assembler.

Index > Main > FASMLIB tutorial part 4 - Error Handling

Author
Thread Post new topic Reply to topic
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid
before reading this chapter, i suggest you to browse doc/general.txt from latest fasmlib package.

Up to now we didn't discuss error handling any deeper. We just jumped to some "error" label which just displayed some fixed error message. Of course FASMLIB gives you a (little) more than this.

Everytime when FASMLIB function return with CF=1, it also sets EAX to hold error code. Each error code has upcase name prefixed with ERR_, for example ERR_INVALID_HANDLE.

This error code is not just some number, like in most languages, but it is also pointer to corresponding error description. So in fact, we can define error code like this:
Code:
ERR_INVALID_HANDLE db "Invalid handle",0    


so after error is returned, you can just output string pointed by EAX. Here is example from tutorial part 2, with error message output added:
Code:
format PE console

include "%FASMINC%/win32axp.inc"

SYSTEM equ win32
include "fasmlib/fasmlib.inc"
include "fasmlib/process.inc"
include "fasmlib/mem.inc"
include "fasmlib/str.inc"
include "fasmlib/stream.inc"

.code

start:
        ;initialize modules
        call mem.init
        jc error
        call str.init
        jc error
        call stream.init
        jc error

        ;display _string
        push dword _string
        push [stream.stdout]
        call stream.write
        jc error

        ;uninitialize modules
        call stream.uninit
        jc error
        call str.uninit
        jc error
        call mem.uninit
        jc error
        
        ;exit process
        push dword 0
        call exit

error:  
        ;save error code in EBX
        mov ebx,eax

        ;try to write error message to stderr
        push _error
        push [stream.stderr]
        call stream.write

        ;display error message
        push ebx
        push [stream.stderr]
        call stream.write

        ;display end of line
        push _eol
        push [stream.stderr]
        call stream.write

        ;try to uninitialize what we can, without further error checking
        call stream.uninit
        call str.uninit
        call mem.uninit

        ;exit with code 1
        push dword 1
        call exit

.data
        _error db "Error: ",0
        _string db "Hell o' world",0
        _eol db 13,10,0
        IncludeIData
        IncludeUData

.end start    
(we are using stream.write mentioned in tutorial part 3 second post)

Note that most procedures from modules that need initialization can return ERR_MODULE_NOT_INITIALIZED, when module is not initialized. These are not mentioned in documentation.

Note that platform-specific procedures always can return ERR_UNKNOWN. See doc/general.txt for explaination of what is platform-specific procedure. See documentation of procedure see if it is platform specific, every such has a note that it is platform-specific. For this reason, ERR_UNKNOWN is not mentioned in documentation.

This means that altough some procedure says "error: none" in documentation, it can still return these two errors, on given cases.

All other errors are mentioned in documentation. But be aware that more errors can be returned in future versions, so when going to newer release of FASMLIB with your project, carefully read whatsnew.txt.

That is, in fact, all we need for error handling. If you handle error somehow, or want to just ignore it, you can just throw away value in EAX, you don't need to do anything else.

simple, eh?
Post 10 Sep 2006, 20:37
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
RedGhost



Joined: 18 May 2005
Posts: 443
Location: BC, Canada
RedGhost
It's good to have a solid error handling system. Personally I usually don't check for errors and when I do it's sloppy, I have terrible programming practice Sad

_________________
redghost.ca
Post 12 Sep 2006, 23:45
View user's profile Send private message AIM Address MSN Messenger Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid
yup, in FASM you just have to add "jc error" for at least some error handling... it's still better to exit with leaks than to crash.

i was even thinking about some try-catch macros, where you wouldn't even have to write those "jc"s, but i am not sure if it is a good idea. It would be possible with minimal instructions overhead, like:

Code:
try
libcall func1, [a], b, eax
libcall func2, 123
...

catch ERR_FILE_NOT_FOUND:
jmp retry

catch:  ;catch all others
push eax
libcall stream.write, "error:"
pop eax
libcall stream.write, [eax]
libcall exit, 0    


sorry about using libcall macro in this example, it is not explained in tutorials yet (next part will cover it... maybe), i am lazy to write pure code now Smile
resultine code would be something like this:
Code:

;libcall func1, [a], b, eax
push eax
push b
push [a]
call func1
jc ..catch

;libcall func2, 123
push 123
call func2
jc ..catch

...

..catch_ERR_FILE_NOT_FOUND:
cmp eax, ERR_FILE_NOT_FOUND
jne ..catch_all

jmp retry

;catch:
..catch_all:
etc...    


it would be neatly possible, but i am afraid that people will get bad practice with ignoring error handling (you know Wink ) with this.

maybe very later
Post 13 Sep 2006, 06:31
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
ChrisLeslie



Joined: 04 Jun 2006
Posts: 50
Location: Australia
ChrisLeslie
My approach to error handling has been to simply write a message to std out with premature exit upon an error for all library procedures, or macros, that require them. Essentially, string routines than may violate the string boundary as well as disk access. This requires decent error catching code in the procedures. Without such an approach I fear that I would be forever chasing bugs and mysterious crashes. For me, console messages are an indispensible diagnostic and debuging tool.

Chris
Post 14 Sep 2006, 07:46
View user's profile Send private message Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid
why not? fasm allows this too. and by the way, in examples contained in tutorial, error handling is just what you described.

here is simple trace what happens after an error:

- FASMLIB routine calls system
- returns with error
- system error code is translated to fasm error code / error message pointer
- fasmlib routine returns to caller with this error

and caller then can (like in my examples):

- notices error happened
- jumps to some "error:" label common for all errors
- displays error (calls str.ptr, str.len, str.writebuf)
- exits

... easy ...
Post 14 Sep 2006, 10:30
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.

Website powered by rwasa.