flat assembler
Message board for the users of flat assembler.

Index > Compiler Internals > [bug] fastcall param's byte/word override.

Author
Thread Post new topic Reply to topic
fasmnewbie



Joined: 01 Mar 2011
Posts: 555
fasmnewbie 16 Mar 2018, 09:51
Code:
        ;...
        else if size@param = 1
         if ~ param eq r8b
          mov r8b,param
          and r8,0xff   ;--> missing?
         end if
        end if
        ;...    


Only for r8 and r9. RCX, RDX working fine. This won't work

Code:
fastcall [printf],addr fmt,byte[ok],byte[nope1],byte[nope2],...    
Post 16 Mar 2018, 09:51
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20299
Location: In your JS exploiting you and your system
revolution 16 Mar 2018, 11:10
Or perhaps use movzx.
Post 16 Mar 2018, 11:10
View user's profile Send private message Visit poster's website Reply with quote
fasmnewbie



Joined: 01 Mar 2011
Posts: 555
fasmnewbie 16 Mar 2018, 11:34
yup.

I think the bug affects the entire parameter set, not just r8,r9.
Post 16 Mar 2018, 11:34
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8351
Location: Kraków, Poland
Tomasz Grysztar 16 Mar 2018, 13:27
The assumption was that if you pass an argument with a size of 1 byte, the higher bytes are undefined. Note that the same thing happens on the stack:
Code:
          ; ...
          else if size@param = 2
           mov ax,param
           mov [rsp+(counter-1)*8],ax
          else
           mov al,param
           mov [rsp+(counter-1)*8],al
          end if
          ; ...    
Only that one byte of reserved stack space gets altered, the higher ones stay undefined. If you need to actually pass a larger value, you have to provide the value of the adequate size to the "fastcall" macro.
Post 16 Mar 2018, 13:27
View user's profile Send private message Visit poster's website Reply with quote
fasmnewbie



Joined: 01 Mar 2011
Posts: 555
fasmnewbie 16 Mar 2018, 17:34
In my opinion, the higher bytes should not be left undefined though. It serves no practical purposes other than giving the users a wrong semantic of what the override byte means. It gives the impression that for example using a "byte" override uses the same quantity as using a qword, which is correct from CPU's POV, but not so from high-level POV, which is what "fastcall" is all about. Besides, byte is a strong semantic keyword though.

For example;

Code:
        section '.data' data readable writeable
fmt     db '%02x',0ah,0
val     dq 1177345566h

        section '.text' code readable executable
main:
        sub     rsp,40

        movzx    ebx,byte[val]
        fastcall [printf],fmt,bl

        call    [getchar]
        mov     rcx,0
        call    [exit]    


What came out was "402066" for BL but correctly displays "66" when using EBX. Now here the semantic is reversed - the byte register returns larger quantity while a 32-bit register returns a byte.

After modifying the "fastcall" macro (via RDX), both gives the correct semantic of a "byte".

Just an opinion.
Post 16 Mar 2018, 17:34
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8351
Location: Kraków, Poland
Tomasz Grysztar 17 Mar 2018, 13:00
The semantics of a byte-sized parameter to "fastcall" macro is that the argument passed is of a type with such size. It is expected that you use it when calling a function that takes an argument with such type, like when you use the "proc" macro with an argument with ":byte" modifier:
Code:
proc tester, p1,p2,p3,p4,p5:byte
        ; ...
        mov     al,[p5]
        ; ...
endp
        ; ...
        fastcall tester,1,2,3,4,byte 5
    
Post 17 Mar 2018, 13:00
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20299
Location: In your JS exploiting you and your system
revolution 17 Mar 2018, 22:11
I think that is too restrictive on usage. There are many API function where passing in bytes from a string is useful but we can't know the underlying code.to confirm that it uses the byte as we require. So when we don't know the nature of the called code we then have to be coding extra instructions to ensure the whole qword is zeroed. It is more work for the poor programer and it doesn't really follow the principal of least surprise.
Post 17 Mar 2018, 22:11
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8351
Location: Kraków, Poland
Tomasz Grysztar 18 Mar 2018, 07:29
If macro was expected to cast the arguments into appropriate type, it would need to have the signature of the function declared. These macros do not need such declaration and are "low level", with the assumption usual to assembly languages, that the programmer knows what exact types of data the called function expects.
Post 18 Mar 2018, 07:29
View user's profile Send private message Visit poster's website 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-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.