flat assembler
Message board for the users of flat assembler.

flat assembler > Unix > Mach-O objects made with fasmg

Author
Thread Post new topic Reply to topic
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6862
Location: Kraków, Poland
After I got the Mach-O executables more or less working the next step is to extend the macros so that they can build linkable objects as well.

I have prepared the macros to create symbol tables and relocations - you may notice that they are a relatively simple addition on top of the basic layers I created earlier for the executable output. I managed to assemble and then successfully link (with LD) the following 32-bit example consisting of two objects:
Code:
include '80386.inc' use32 MachO.Settings.FileType equ MH_OBJECT include 'macho.inc' public start extrn writemsg SYS_exit = 1 section '__TEXT':'__text' start: mov esi,msg call writemsg push 1 mov eax,SYS_exit sub esp,4 int 0x80 section '__TEXT':'__cstring' msg db "Relocated and ready!",0xA,0
Code:
include '80386.inc' use32 MachO.Settings.FileType equ MH_OBJECT include 'macho.inc' public writemsg SYS_write = 4 section '__TEXT':'__text' writemsg: mov edi,esi mov ecx,-1 xor al,al repne scasb neg ecx sub ecx,2 push ecx push esi push 1 mov eax,SYS_write sub esp,4 int 0x80 add esp,4*4 ret


Note that when Mach-O is used as an object, all sections should reside in a single unnamed segment, but each section in addition to its own name needs to specify the name of a segment it is intended for. Thus the unusual syntax in the above samples.

PS. I have not created any 64-bit objects yet. There are going to be some differences in relocations and perhaps some other things to adjust to make them work.


Description: Mach-O formatting macros with example objects
Download
Filename: machO.zip
Filesize: 9.1 KB
Downloaded: 78 Time(s)

Post 27 Aug 2017, 22:11
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6862
Location: Kraków, Poland
With a small tweak in the relocation generating macro I was able to get 64-bit objects to work, too. The sources are like:
Code:
include 'x64.inc' use64 MachO.Settings.FileType equ MH_OBJECT MachO.Settings.ProcessorType equ CPU_TYPE_X86_64 MachO.Settings.ProcessorSubtype equ CPU_SUBTYPE_X86_64_ALL include 'macho.inc' section '__TEXT':'__text' public start extrn writemsg extrn exit start: lea rsi,[msg] call writemsg call exit section '__DATA':'__data' msg db 'Relocated and ready!',0Ah,0
Code:
include 'x64.inc' use64 MachO.Settings.FileType equ MH_OBJECT MachO.Settings.ProcessorType equ CPU_TYPE_X86_64 MachO.Settings.ProcessorSubtype equ CPU_SUBTYPE_X86_64_ALL include 'macho.inc' section '__TEXT':'__text' public writemsg public exit SYSCALL_CLASS_UNIX = 2 SYSCALL_CLASS_SHIFT = 24 define SYSCALL_CONSTRUCT_UNIX SYSCALL_CLASS_UNIX shl SYSCALL_CLASS_SHIFT + SYS_exit = 1 SYS_write = 4 writemsg: mov rdi,rsi or rcx,-1 xor al,al repne scasb neg rcx sub rcx,2 mov rdx,rcx mov rdi,1 mov rax,SYSCALL_CONSTRUCT_UNIX(SYS_write) syscall retn exit: mov rdi,rax mov rax,SYSCALL_CONSTRUCT_UNIX(SYS_exit) syscall
Post 28 Aug 2017, 17:07
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6862
Location: Kraków, Poland
As an additional test of the macros I have assembled the MacOS version of fasmg as a linkable object and it appears to be working correctly. In the current packaging "source/macos/fasmg.asm" assembles directly to executable, to get an object instead it needs to be replaced with the following:
Code:
match ,{ err ; fasm 1 assembly not supported } match -,{ else include 'selfhost.inc' end match _ equ } format MachO public main as '_main' include '../version.inc' extrn '_malloc' as libc.malloc extrn '_realloc' as libc.realloc extrn '_free' as libc.free extrn '_fopen' as libc.fopen extrn '_fclose' as libc.fclose extrn '_fread' as libc.fread extrn '_fwrite' as libc.fwrite extrn '_fseek' as libc.fseek extrn '_ftell' as libc.ftell extrn '_time' as libc.time extrn '_write' as libc.write extrn '_getenv' as getenv extrn '_gettimeofday' as gettimeofday extrn '_exit' as exit struct timeval time_t dd ? suseconds_t dd ? ends section '__TEXT':'__text' align 16 main: mov ecx,[esp+4] mov [argc],ecx mov ebx,[esp+8] mov [argv],ebx call system_init mov esi,_logo xor ecx,ecx call display_string call get_arguments jc display_usage_information xor al,al mov ecx,[verbosity_level] jecxz init or al,TRACE_ERROR_STACK dec ecx jz init or al,TRACE_DISPLAY init: call assembly_init ccall gettimeofday,start_time,0 assemble: mov esi,[initial_commands] mov edx,[source_path] call assembly_pass jc assembly_done mov eax,[current_pass] cmp eax,[maximum_number_of_passes] jb assemble call show_display_data mov ebx,_code_cannot_be_generated jmp fatal_error assembly_done: call show_display_data cmp [first_error],0 jne assembly_failed mov eax,[current_pass] mov edi,string_buffer call itoa call display_string mov esi,_passes cmp [current_pass],1 jne display_passes_suffix mov esi,_pass display_passes_suffix: xor ecx,ecx call display_string ccall gettimeofday,end_time,0 mov eax,[end_time.time_t] sub eax,[start_time.time_t] mov ecx,1000000 mul ecx add eax,[end_time.suseconds_t] adc edx,0 sub eax,[start_time.suseconds_t] sbb edx,0 add eax,50000 mov ecx,1000000 div ecx mov ebx,eax mov eax,edx xor edx,edx mov ecx,100000 div ecx mov [tenths_of_second],eax xchg eax,ebx or ebx,eax jz display_output_length mov edi,string_buffer call itoa call display_string mov esi,_message_suffix mov ecx,1 call display_string mov eax,[tenths_of_second] mov edi,string_buffer call itoa call display_string mov esi,_seconds xor ecx,ecx call display_string display_output_length: call get_output_length push eax mov edi,string_buffer call itoa call display_string pop eax mov esi,_bytes cmp eax,1 jne display_bytes_suffix mov esi,_byte display_bytes_suffix: xor ecx,ecx call display_string mov esi,_new_line xor ecx,ecx call display_string mov edi,[output_path] call write_output_file jc write_failed call assembly_shutdown call system_shutdown ccall exit,0 assembly_failed: call show_errors call assembly_shutdown call system_shutdown ccall exit,2 write_failed: mov ebx,_write_failed jmp fatal_error out_of_memory: mov ebx,_out_of_memory jmp fatal_error fatal_error: mov esi,_error_prefix xor ecx,ecx call display_error_string mov esi,ebx xor ecx,ecx call display_error_string mov esi,_message_suffix xor ecx,ecx call display_error_string call assembly_shutdown call system_shutdown ccall exit,3 display_usage_information: mov esi,_usage xor ecx,ecx call display_string call system_shutdown ccall exit,1 get_arguments: xor eax,eax mov [initial_commands],eax mov [source_path],eax mov [output_path],eax mov [maximum_number_of_passes],100 mov [maximum_number_of_errors],1 mov [maximum_depth_of_stack],10000 mov ecx,[argc] mov ebx,[argv] add ebx,4 dec ecx jz error_in_arguments get_argument: mov esi,[ebx] mov al,[esi] cmp al,'-' je get_option cmp [source_path],0 jne get_output_file mov [source_path],esi jmp next_argument get_output_file: cmp [output_path],0 jne error_in_arguments mov [output_path],esi jmp next_argument get_option: inc esi lodsb cmp al,'e' je set_errors_limit cmp al,'E' je set_errors_limit cmp al,'i' je insert_initial_command cmp al,'I' je insert_initial_command cmp al,'p' je set_passes_limit cmp al,'P' je set_passes_limit cmp al,'r' je set_recursion_limit cmp al,'R' je set_recursion_limit cmp al,'v' je set_verbose_mode cmp al,'V' je set_verbose_mode error_in_arguments: stc ret set_verbose_mode: cmp byte [esi],0 jne get_verbose_setting dec ecx jz error_in_arguments add ebx,4 mov esi,[ebx] get_verbose_setting: call get_option_value cmp edx,2 ja error_in_arguments mov [verbosity_level],edx jmp next_argument set_errors_limit: cmp byte [esi],0 jne get_errors_setting dec ecx jz error_in_arguments add ebx,4 mov esi,[ebx] get_errors_setting: call get_option_value test edx,edx jz error_in_arguments mov [maximum_number_of_errors],edx jmp next_argument set_recursion_limit: cmp byte [esi],0 jne get_recursion_setting dec ecx jz error_in_arguments add ebx,4 mov esi,[ebx] get_recursion_setting: call get_option_value test edx,edx jz error_in_arguments mov [maximum_depth_of_stack],edx jmp next_argument set_passes_limit: cmp byte [esi],0 jne get_passes_setting dec ecx jz error_in_arguments add ebx,4 mov esi,[ebx] get_passes_setting: call get_option_value test edx,edx jz error_in_arguments mov [maximum_number_of_passes],edx next_argument: add ebx,4 dec ecx jnz get_argument cmp [source_path],0 je error_in_arguments cmp [output_path],0 je error_in_arguments clc ret get_option_value: xor eax,eax mov edx,eax find_option_value: cmp byte [esi],20h jne get_option_digit inc esi jmp find_option_value get_option_digit: lodsb test al,al jz option_value_ok sub al,30h jc invalid_option_value cmp al,9 ja invalid_option_value imul edx,10 jo invalid_option_value add edx,eax jc invalid_option_value jmp get_option_digit option_value_ok: dec esi clc ret invalid_option_value: stc ret insert_initial_command: cmp byte [esi],0 jne measure_initial_command dec ecx jz error_in_arguments add ebx,4 mov esi,[ebx] measure_initial_command: push ebx ecx edi mov edi,esi or ecx,-1 xor al,al repne scasb not ecx dec ecx mov edi,[initial_commands] lea eax,[ecx+2] test edi,edi jz allocate_initial_commands_buffer mov edx,[initial_commands_length] add edi,edx add eax,edx cmp eax,[initial_commands_maximum_length] ja grow_initial_commands_buffer copy_initial_command: rep movsb mov ax,0Ah stosw dec edi sub edi,[initial_commands] mov [initial_commands_length],edi pop edi ecx ebx jmp next_argument allocate_initial_commands_buffer: push ecx mov ecx,eax call malloc jc out_of_memory mov [initial_commands],eax mov [initial_commands_maximum_length],ecx mov edi,eax pop ecx jmp copy_initial_command grow_initial_commands_buffer: push ecx mov ecx,eax mov eax,[initial_commands] call realloc jc out_of_memory mov [initial_commands],eax mov [initial_commands_maximum_length],ecx mov edi,eax add edi,[initial_commands_length] pop ecx jmp copy_initial_command include 'system.inc' include '../assembler.inc' include '../symbols.inc' include '../expressions.inc' include '../conditions.inc' include '../directives.inc' include '../floats.inc' include '../errors.inc' include '../map.inc' include '../reader.inc' include '../output.inc' include '../console.inc' section '__TEXT':'__cstring' align 4 _logo db 'flat assembler version g.',VERSION,10,0 _usage db 'Usage: fasmg source output',10 db 'Optional settings:',10 db ' -p limit Set the maximum allowed number of passes (default 100)',10 db ' -e limit Set the maximum number of displayed errors (default 1)',10 db ' -r limit Set the maximum depth of stack (default 10000)',10 db ' -v flag Enable or disable showing all lines from the stack (default 0)',10 db ' -i command Insert instruction at the beginning of source',13,10 db 0 _pass db ' pass, ',0 _passes db ' passes, ',0 _dot db '.' _seconds db ' seconds, ',0 _byte db ' byte.',0 _bytes db ' bytes.',0 _write_failed db 'failed to write the output file',0 _out_of_memory db 'not enough memory to complete the assembly',0 _code_cannot_be_generated db 'could not generate code within the allowed number of passes',0 _open_mode db 'r',0 _create_mode db 'w',0 include '../tables.inc' include '../messages.inc' section '__DATA':'__data' align 4 include '../variables.inc' source_path dd ? output_path dd ? maximum_number_of_passes dd ? initial_commands dd ? initial_commands_length dd ? initial_commands_maximum_length dd ? argc dd ? argv dd ? timestamp dq ? start_time timeval end_time timeval tenths_of_second dd ? verbosity_level dd ? string_buffer rb 100h path_buffer rb 1000h
Post 01 Sep 2017, 20:47
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 © 2004-2018, Tomasz Grysztar.

Powered by rwasa.