flat assembler
Message board for the users of flat assembler.
Index
> Non-x86 architectures > aarch64 includes for fasmg Goto page Previous 1, 2 |
Author |
|
Tomasz Grysztar 23 Sep 2017, 21:14
I have edited the above code, because it had some bugs. I also changed it so it now uses this option:
Code: ELF.Settings.LoadHeaders = 1 Please let me know if this works. |
|||
23 Sep 2017, 21:14 |
|
tthsqe 24 Sep 2017, 11:15
Alright! works fine now. Would it be correct to say that these changes to the formatting macro are due to bugs in the interpreter (i.e. that none of these requirements are dictated by the elf standard)?
|
|||
24 Sep 2017, 11:15 |
|
Tomasz Grysztar 24 Sep 2017, 13:15
tthsqe wrote: Alright! works fine now. Would it be correct to say that these changes to the formatting macro are due to bugs in the interpreter (i.e. that none of these requirements are dictated by the elf standard)? There is, however, an additional problem. The way I implemented subsegments above causes their entries to follow the entry of their "parent" segment in program headers. But the specification states this: ELF Specification wrote: PT_INTERP |
|||
24 Sep 2017, 13:15 |
|
Tomasz Grysztar 24 Sep 2017, 15:00
Please test this variant. It uses no "subsegment" syntax, only the "LoadHeaders" setting, but the setting automatically overlays "interpreter" and "dynamic" segments onto loadable ones, just like the program headers. And this time it should not violate the ELF specification as long as you ensure that "segment interpreter" is the first one defined.
Code: ELFCLASSNONE = 0 ELFCLASS32 = 1 ELFCLASS64 = 2 ELFDATANONE = 0 ELFDATA2LSB = 1 ELFDATA2MSB = 2 ELFOSABI_NONE = 0 ELFOSABI_HPUX = 1 ELFOSABI_NETBSD = 2 ELFOSABI_GNU = 3 ELFOSABI_LINUX = 3 ELFOSABI_SOLARIS = 6 ELFOSABI_AIX = 7 ELFOSABI_IRIX = 8 ELFOSABI_FREEBSD = 9 ELFOSABI_TRU64 = 10 ELFOSABI_MODESTO = 11 ELFOSABI_OPENBSD = 12 ELFOSABI_OPENVMS = 13 ELFOSABI_NSK = 14 ELFOSABI_AROS = 15 ELFOSABI_FENIXOS = 16 ELFOSABI_CLOUDABI = 17 ELFOSABI_OPENVOS = 18 ET_NONE = 0 ET_REL = 1 ET_EXEC = 2 ET_DYN = 3 ET_CORE = 4 ET_LOPROC = 0xff00 ET_HIPROC = 0xffff EM_NONE = 0 EM_M32 = 1 EM_SPARC = 2 EM_386 = 3 EM_68K = 4 EM_88K = 5 EM_860 = 7 EM_MIPS = 8 EM_X86_64 = 62 EV_NONE = 0 EV_CURRENT = 1 PT_NULL = 0 PT_LOAD = 1 PT_DYNAMIC = 2 PT_INTERP = 3 PT_NOTE = 4 PT_SHLIB = 5 PT_PHDR = 6 PT_GNU_EH_FRAME = 0x6474e550 PT_GNU_STACK = 0x6474e551 PT_LOPROC = 0x70000000 PT_HIPROC = 0x7fffffff PF_X = 1 PF_W = 2 PF_R = 4 PF_MASKOS = 0x0ff00000 PF_MASKPROC = 0xf0000000 macro align boundary,value:? db (boundary-1)-($+boundary-1) mod boundary dup value end macro ELF:: namespace ELF if defined Settings.Class CLASS := Settings.Class else CLASS := ELFCLASS32 end if if defined Settings.Machine MACHINE := Settings.Machine else MACHINE := EM_386 end if if defined Settings.ABI ABI := Settings.ABI else ABI := ELFOSABI_NONE end if if defined Settings.BaseAddress BASE_ADDRESS := Settings.BaseAddress else BASE_ADDRESS := 8048000h end if if defined Settings.LoadHeaders LOAD_HEADERS := Settings.LoadHeaders else LOAD_HEADERS := 0 end if Header: e_ident db 0x7F,'ELF',CLASS,ELFDATA2LSB,EV_CURRENT,ABI,(16-$) dup 0 e_type dw ET_EXEC e_machine dw MACHINE e_version dd EV_CURRENT if CLASS <> ELFCLASS64 e_entry dd start e_phoff dd ProgramHeader e_shoff dd 0 e_flags dd 0 e_ehsize dw ProgramHeader e_phentsize dw SEGMENT_HEADER_LENGTH e_phnum dw NUMBER_OF_SEGMENTS e_shentsize dw 28h e_shnum dw 0 e_shstrndx dw 0 else e_entry dq start e_phoff dq ProgramHeader e_shoff dq 0 e_flags dd 0 e_ehsize dw ProgramHeader e_phentsize dw SEGMENT_HEADER_LENGTH e_phnum dw NUMBER_OF_SEGMENTS e_shentsize dw 40h e_shnum dw 0 e_shstrndx dw 0 end if ProgramHeader: if CLASS <> ELFCLASS64 p_type dd PT_LOAD p_offset dd 0 p_vaddr dd BASE_ADDRESS p_paddr dd BASE_ADDRESS p_filesz dd 0 p_memsz dd 0 p_flags dd PF_R+PF_W+PF_X p_align dd 1000h else p_type dd PT_LOAD p_flags dd PF_R+PF_W+PF_X p_offset dq 0 p_vaddr dq BASE_ADDRESS p_paddr dq BASE_ADDRESS p_filesz dq 0 p_memsz dq 0 p_align dq 1000h end if SEGMENT_HEADER_LENGTH = $ - ProgramHeader db (NUMBER_OF_SEGMENTS-1)*SEGMENT_HEADER_LENGTH dup 0 HEADERS_OFFSET = 0 HEADERS_BASE = BASE_ADDRESS OVERLAY_HEADERS = LOAD_HEADERS SEGMENT_INDEX = 0 DEFINED_SEGMENT = 0 SEGMENT_TYPE = PT_LOAD FILE_OFFSET = $% SEGMENT_BASE = BASE_ADDRESS + FILE_OFFSET and 0FFFh org SEGMENT_BASE start: end namespace macro entry? address* namespace ELF store address at ELF:e_entry end namespace end macro macro segment? namespace ELF DEFINED_SEGMENT_SIZE = $ - SEGMENT_BASE if (DEFINED_SEGMENT | DEFINED_SEGMENT_SIZE > 0) & SEGMENT_TYPE = PT_LOAD & OVERLAY_HEADERS FILE_OFFSET = HEADERS_OFFSET SEGMENT_BASE = HEADERS_BASE OVERLAY_HEADERS = 0 end if store SEGMENT_BASE at ELF:p_vaddr+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH store SEGMENT_BASE at ELF:p_paddr+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH store FILE_OFFSET at ELF:p_offset+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH if SEGMENT_TYPE = PT_LOAD RAW_DATA_SIZE = $%% - FILE_OFFSET SEGMENT_SIZE = $ - SEGMENT_BASE store RAW_DATA_SIZE at ELF:p_filesz+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH store SEGMENT_SIZE at ELF:p_memsz+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH if DEFINED_SEGMENT | DEFINED_SEGMENT_SIZE > 0 FILE_OFFSET = $%% align 1000h SEGMENT_BASE = $ + FILE_OFFSET and 0FFFh end if section SEGMENT_BASE else if LOAD_HEADERS & OVERLAY_HEADERS = 0 & ( SEGMENT_TYPE = PT_INTERP | SEGMENT_TYPE = PT_DYNAMIC ) OVERLAY_HEADERS = 1 HEADERS_OFFSET = FILE_OFFSET HEADERS_BASE = SEGMENT_BASE end if FILE_OFFSET = $% SEGMENT_SIZE = $ - SEGMENT_BASE store SEGMENT_SIZE at ELF:p_filesz+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH store SEGMENT_SIZE at ELF:p_memsz+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH if OVERLAY_HEADERS = 0 SEGMENT_BASE = SEGMENT_BASE and not 0FFFh + FILE_OFFSET and 0FFFh else SEGMENT_BASE = $ end if if $% > $%% store 0:byte at $-1 end if org SEGMENT_BASE end if if DEFINED_SEGMENT | DEFINED_SEGMENT_SIZE > 0 SEGMENT_INDEX = SEGMENT_INDEX + 1 end if end namespace end macro macro segment? attributes* namespace ELF segment SEGMENT_TYPE = PT_LOAD SEGMENT_FLAGS = 0 local seq,list define seq attributes while 1 match car cdr, seq define list car define seq cdr else match any, seq define list any end match break end match end while irpv attribute, list match =readable?, attribute SEGMENT_FLAGS = SEGMENT_FLAGS or PF_R else match =writeable?, attribute SEGMENT_FLAGS = SEGMENT_FLAGS or PF_W else match =executable?, attribute SEGMENT_FLAGS = SEGMENT_FLAGS or PF_X else match =interpreter?, attribute SEGMENT_TYPE = PT_INTERP else match =dynamic?, attribute SEGMENT_TYPE = PT_DYNAMIC else match =note?, attribute SEGMENT_TYPE = PT_NOTE else match =gnustack?, attribute SEGMENT_TYPE = PT_GNU_STACK else match =gnuehframe?, attribute SEGMENT_TYPE = PT_GNU_EH_FRAME else err 'invalid argument' end match end irpv DEFINED_SEGMENT = 1 store SEGMENT_TYPE at ELF:p_type+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH store SEGMENT_FLAGS at ELF:p_flags+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH if SEGMENT_TYPE = PT_LOAD store 1000h at ELF:p_align+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH else store 1 at ELF:p_align+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH end if end namespace end macro postpone purge segment? segment namespace ELF NUMBER_OF_SEGMENTS := SEGMENT_INDEX end namespace end postpone |
|||
24 Sep 2017, 15:00 |
|
Tomasz Grysztar 25 Sep 2017, 13:16
One bug-fix later, I have I included the above in the standard fasmg package. Without "LoadHeaders" set it works in "fasm 1 compatibility" mode still, and with the option set I believe it produces specification-compliant executables that should fulfill these loader requiremenets. But please confirm.
|
|||
25 Sep 2017, 13:16 |
|
tthsqe 28 Sep 2017, 14:58
Of course it works.[/code]
|
|||
28 Sep 2017, 14:58 |
|
Tomasz Grysztar 15 Apr 2018, 16:32
How did the macros turn out? Perhaps I could be of assistance still to solve any problems (like bringing more syntactical compatibility with other ARM assemblers)?
Also, if you would allow this, I would gladly use your macros as a basis to get some ARM examples packaged officially with fasmg (with the original authorship credited in the source). |
|||
15 Apr 2018, 16:32 |
|
tthsqe 17 Apr 2018, 08:02
The macros seem to be fine, and are for the most part compatible with gas syntax. I only developed them to a point were they could create a working exe on my phone. For example, I know of a case of an instruction that does not assemble correctly, so I avoided using this instruction. Also, a majority of invalid instructions are reported as an error, but I cannot guarantee that they all are. I simply have not had the time to test it very thoroughly, and my cross compiler installation just got hosed. The github repo is not going anywhere - why not simply put a link to it?
|
|||
17 Apr 2018, 08:02 |
|
Tomasz Grysztar 17 Apr 2018, 16:43
I have already included a link to it in the official list of fasmg-related resources, but what I had in mind is to make a set of macros that would basically bring the functionality of FASMARM to the new engine, just like my main x86 macros bring compatibility with the original assembler. It seems I have to work on this myself anyway, but what you have already done could serve as a starting point.
|
|||
17 Apr 2018, 16:43 |
|
tthsqe 17 Apr 2018, 20:35
Sure, I think you will find the macros to be a good starting point for a more polished assembler for aarch64. I will try to document better how they work and the ones I know to be buggy. I did pass the list of instructions provided by revolution through fasmg and gas and observed a match.
I have no idea about 32bit ARM. |
|||
17 Apr 2018, 20:35 |
|
alorent 12 Apr 2023, 02:09
Hi,
First of all, thanks tthsq for the great support of arm64 on FASMG. I'm trying to read the flags registers, so I use the following instruction: Code: mrs x0, NZCV But it looks like the instruction is not recognized. I have tried with upper/lowercases, etc. Thanks! |
|||
12 Apr 2023, 02:09 |
|
Tomasz Grysztar 12 Apr 2023, 11:23
Looking at the source, the implementation of this instruction seems to cover just a couple of cases:
Code: macro mrs a*, b* aarch64.parse_operand @op0, a match =actlr_el1?, b dd 0xd5381020 + (@op0.data shl 0) else match =vttbr_el2?, b dd 0xd53c2100 + (@op0.data shl 0) else match =spsel?, b dd 0xd5384200 + (@op0.data shl 0) else match =s3_2_c3_c4_5?, b dd 0xd53a34a0 + (@op0.data shl 0) else err 'invalid operand' end match end macro Code: else match =nzcv?, b dd 0xd53b4200 + (@op0.data shl 0) You could also change it into something faster and more expandable: Code: namespace aarch64.mrs actlr_el1? = 0xd5381020 vttbr_el2? = 0xd53c2100 spsel? = 0xd5384200 s3_2_c3_c4_5? = 0xd53a34a0 nzcv? = 0xd53b4200 end namespace macro mrs a*, b* aarch64.parse_operand @op0, a if defined aarch64.mrs.b dd aarch64.mrs.b + (@op0.data shl 0) else err 'invalid operand' end if end macro I had similarly encountered little issues with these headers, even when I was preparing the simplest example for Windows on ARM64, and I just quickly corrected them in the headers so that I could keep going (you can find that version of aarch64.inc in the package that comes with my executable formats tutorial, which now includes some ARM64 examples as well). Unfortunately I have not been able to get a response from tthsq with regards to further development of these includes, perhaps we need to take it from here. |
|||
12 Apr 2023, 11:23 |
|
alorent 12 Apr 2023, 15:22
Thanks a lot Tomasz! I took your modified "aarch64.inc" with the LDP fix and also added the "nzcv" extension as you proposed.
It looks the same happens for the "msr" instruction. I have modified the aarch64.inc file: Code: macro msr a*, b* aarch64.parse_operand @op0, b match =actlr_el1?, a dd 0xd5181020 + (@op0.data shl 0) else match =vttbr_el2?, a dd 0xd51c2100 + (@op0.data shl 0) else match =spsel?, a dd 0xd5184200 + (@op0.data shl 0) else match =s3_2_c3_c4_5?, a dd 0xd51a34a0 + (@op0.data shl 0) else match =nzcv?, a dd 0xd51b4200 + (@op0.data shl 0) else err 'invalid operand' end match end macro Thanks! |
|||
12 Apr 2023, 15:22 |
|
alorent 13 Apr 2023, 14:33
Using the "aarch.inc" or FASMARM, I can assembly the following:
Code: add x1, sp, x1 but it produces error when I assemble: Code: add x1, x1, sp Is that a bug in the include or FASMARM? Or maybe I'm writing a wrong instruction? (though the two above should be equivalent) Thanks! |
|||
13 Apr 2023, 14:33 |
|
revolution 13 Apr 2023, 16:40
Technically "add x1, x1, sp" is not valid because sp can't be encoded as the third register, it would encode xzr instead.
But you are correct, the "add x1, sp, x1" is 100% equivalent. It would be good if fasmarm could swap the registers automatically, as it does for arm32. |
|||
13 Apr 2023, 16:40 |
|
alorent 14 Apr 2023, 05:52
Thanks revolution! Appreciated!
|
|||
14 Apr 2023, 05:52 |
|
tthsqe 16 May 2023, 23:43
I should have given the green light. Let's see aarch64 in the official.
|
|||
16 May 2023, 23:43 |
|
Goto page Previous 1, 2 < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.