flat assembler
Message board for the users of flat assembler.

Index > Main > ELF, use16 and relative jumps

Author
Thread Post new topic Reply to topic
alexfru



Joined: 23 Mar 2014
Posts: 80
alexfru 28 Oct 2016, 06:07
Using FASM 1.71.22 I'm assembling the following code:

Code:
format elf
;use32
use16
section ".text" executable
public main
main:
    mov eax, [main]
    mov eax, [ebx + main]
    push dword main
    jz dword foo1 ; jz rel8 (with unnecessary operand size prefix)
    jmp dword foo1 ; jmp rel8 (with unnecessary operand size prefix)
foo1:
    jz dword foo2 ; jz rel32 (with operand size prefix and 32-bit imm, too long!!!)
    jmp dword foo2 ; jmp rel32 (with operand size prefix and 32-bit imm, too long!!!)
    rb 200
foo2:
    ret
    


The disassembly of the beginning of the .text section is
Code:
00000034:i6766A100000000                 mov       eax,[+00000000]
0000003B:i67668B8300000000               mov       eax,[ebx+00000000]
00000043:i666800000000                   push      00000000
00000049:i667403                         je        file:0000004F
0000004C:i66EB00                         jmps      file:0000004F
0000004F:i660F84CE000000                 je        file:00000124
00000056:i66E9C8000000                   jmpn32    file:00000124
    


There are several problems with this code:

    1. I actually must write "dword" in order for the code to assemble at all.
    2. There's an unnecessary operand size prefix generated for short (rel8) jumps.
    3. It would be nice to be able to generate jmp/jcc rel16 instead of jmp/jcc rel32 when assembling 16-bit code into an ELF file. Perhaps, fixing this part alone would fix the two problems above.


Can this be fixed at least for relative jumps (and calls?) within the same assembly file? (This would not require supporting 16-bit relocations in the ELF format)

What this would give me is the ability to use FASM for compiling 16-bit-ish code with my C compiler in addition to NASM and YASM. When I say 16-bit-ish, I mean code for unreal mode. I can patch up the code in the linker to create far calls and the rest can work as-is.
Post 28 Oct 2016, 06:07
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20513
Location: In your JS exploiting you and your system
revolution 28 Oct 2016, 06:16
1. Because the address pointer is greater than 64k
2. It is necessary because you need to convert the address to 32-bit
3. You can, but you need to keep the address pointer below 64k

Why are you using ELF format? ELF has no support for 16-bit code so you are using it out of its normal usage. In short don't do that.
Post 28 Oct 2016, 06:16
View user's profile Send private message Visit poster's website Reply with quote
alexfru



Joined: 23 Mar 2014
Posts: 80
alexfru 28 Oct 2016, 06:43
revolution wrote:
1. Because the address pointer is greater than 64k

Not quite. The top 16 bits of EIP are ignored in (un)real mode. For relative jumps you only care about the distance fitting into 8 or 16/32 bits.

revolution wrote:
2. It is necessary because you need to convert the address to 32-bit

Only if this address ends up in the relocation table, which is not the case for jumps within the same section of the same assembly file.

revolution wrote:
3. You can, but you need to keep the address pointer below 64k

I don't need to do much special about it. As I said above, the E part of EIP is ignored in the CPU. All the functions produced by my compiler will be far-callable and limited to 64KB in size. I can always make their far address to have the offset less than 16 (I do it already for "huge" mode with NASM/YASM).

revolution wrote:
Why are you using ELF format?

I don't want to support many formats. ELF is perfectly suitable for what I'm doing.

revolution wrote:
ELF has no support for 16-bit code so you are using it out of its normal usage. In short don't do that.

Not quite so. Relative branches, at least the rel8 kind within the same section of the same assembly file, should just work and assemble without unnecessary "dword" or operand size prefixes. rel32 is excessive here, but it works too, however the "dword" requirement is extremely inconvenient. Not requiring "dword" would solve the biggest problem of the code simply not assembling. I can probably live with overly long instructions.
Post 28 Oct 2016, 06:43
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8367
Location: Kraków, Poland
Tomasz Grysztar 28 Oct 2016, 06:56
alexfru wrote:
Not quite so. Relative branches, at least the rel8 kind within the same section of the same assembly file, should just work and assemble without unnecessary "dword" or operand size prefixes.
Not when the address is known to be 32-bit and potentially outside of 16-bit range. When you are using the ELF format, the base address for your section (the one that you can alter with ORG) is a 32-bit relocatable value, so the instructions are assembled to allow for this address to be a (potentially large) 32-bit number. This is the natural consequence of using the ELF format, revolution rightly pointed out that this really is not the right format to hold the 16-bit code.

If you need to assemble the code under a different assumption, you have to alter the base address so that assembler knows that it is not going to be a large value. For example:
Code:
format elf
section ".text" executable  
    org 0
    use16
public main
main:
    mov eax, [main] 
    mov eax, [ebx + main] 
    push dword main 
    jz foo1
    jmp foo1
foo1: 
    jz foo2
    jmp foo2
    rb 200 
foo2: 
    ret    
Of course, when you make your base address a non-relocatable value, the assembler is not going to create any relocations for that code - but you stated that you don't need that.

Also, the "main" symbol defined this way is going to be exported as an absolute number (because we made it an absolute number). If you need to export it as an address in relocatable section, you have to modify it like this:
Code:
format elf
section ".text" executable 

    label _main at $$+main
    public _main as 'main'

    org 0
    use16
main:
    mov eax, [main]
    mov eax, [ebx + main] 
    push dword main 
    jz foo1
    jmp foo1
foo1: 
    jz foo2
    jmp foo2
    rb 200 
foo2: 
    ret    
Post 28 Oct 2016, 06:56
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-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.