@@ -1886,9 +1886,9 @@ void genInstrBody(ofstream& outFile, InstrNames instr, int instrNum, bool inputT
18861886 } else if (instr == Ijmp || instr == Ib) {
18871887 outFile <<
18881888 " mov rsi, " << instrNum << " \n "
1889- " cmp rcx, instruction_count\n "
1889+ " cmp rcx, OFFSET FLAT: instruction_count\n "
18901890 " ja jmp_error\n "
1891- " mov rbx, instruction_offsets\n "
1891+ " lea rbx, [rip + instruction_offsets] \n "
18921892 " jmp [rbx+8*rcx]\n " ;
18931893 } else if (instr == Il || instr == Is) { // handled in genCond
18941894 } else if (instr == Iswap) {
@@ -1900,7 +1900,7 @@ void genInstrBody(ofstream& outFile, InstrNames instr, int instrNum, bool inputT
19001900 " call print_unsigned\n " ;
19011901 } else if (instr == Ioutc) {
19021902 outFile <<
1903- " mov rdx, stdout_buff\n "
1903+ " lea rdx, [rip + stdout_buff] \n "
19041904 " mov [rdx], cl\n "
19051905 " mov r8, 1\n "
19061906 " call stdout_write\n " ;
@@ -1950,121 +1950,115 @@ void genAssembly(ofstream& outFile, Instr instr, int instrNum) {
19501950
19511951void generate (ofstream& outFile, vector<Instr>& instrs) {
19521952 outFile <<
1953- " extern ExitProcess\n "
1954- " extern GetStdHandle\n "
1955- " extern WriteFile\n "
1956- " extern ReadFile\n "
1953+ " .intel_syntax noprefix\n "
19571954 " \n "
1958- " section .text\n "
1959- " exit: ; exits the program with code in rax\n "
1955+ " .extern ExitProcess\n "
1956+ " .extern GetStdHandle\n "
1957+ " .extern WriteFile\n "
1958+ " .extern ReadFile\n "
1959+ " \n "
1960+ " .text\n "
1961+ " exit: # exits the program with code in rax\n "
19601962 " mov rcx, rax\n "
1961- " and rsp, -16 ; force 16-byte alignment\n "
1963+ " and rsp, -16 # force 16-byte alignment\n "
19621964 " sub rsp, 32\n "
19631965 " call ExitProcess\n "
19641966 " hlt\n "
1965- " error: ; prints ERROR template, instr number: rsi, message: rdx, r8, errorneous value: rcx, exit(1)\n "
1967+ " error: # prints ERROR template, instr number: rsi, message: rdx, r8, errorneous value: rcx, exit(1)\n "
19661968 " push rcx\n "
19671969 " push r8\n "
19681970 " push rdx\n "
19691971 " push rsi\n "
1970- " mov rdx, ERROR_template\n "
1971- " mov r8, ERROR_template_len\n "
1972+ " lea rdx, [rip + ERROR_template] \n "
1973+ " mov r8, OFFSET FLAT: ERROR_template_len\n "
19721974 " call stderr_write\n "
1973- " pop rax ; print instr number\n "
1975+ " pop rax # print instr number\n "
19741976 " call print_unsigned_err\n "
1975- " pop rdx ; error message\n "
1977+ " pop rdx # error message\n "
19761978 " pop r8\n "
19771979 " call stderr_write\n "
1978- " pop rax ; errorneous value\n "
1980+ " pop rax # errorneous value\n "
19791981 " call print_unsigned_err\n "
1980- " mov rdx, stdout_buff\n "
1981- " mov BYTE [rdx], 10 ; '\\ n'\n "
1982+ " lea rdx, [rip + stdout_buff] \n "
1983+ " mov BYTE PTR [rdx], 10 # '\\ n'\n "
19821984 " mov r8, 1\n "
19831985 " call stderr_write\n "
1984- " mov rax, 1 ; exit(1)\n "
1986+ " mov rax, 1 # exit(1)\n "
19851987 " call exit\n "
19861988 " \n "
1987- " get_std_fds: ; prepares all std fds, regs unsafe!\n "
1988- " sub rsp, 32 ; reserve shadow space\n "
1989- " mov rcx, -10 ; stdin fd\n "
1989+ " get_std_fds: # prepares all std fds, regs unsafe!\n "
1990+ " sub rsp, 32 # reserve shadow space\n "
1991+ " mov rcx, -10 # stdin fd\n "
19901992 " call GetStdHandle\n "
1991- " mov rcx, stdin_fd\n "
1992- " mov [rcx], rax\n "
1993- " mov rcx, -11 ; stdout fd\n "
1993+ " mov QWORD PTR [rip + stdin_fd], rax\n "
1994+ " mov rcx, -11 # stdout fd\n "
19941995 " call GetStdHandle\n "
1995- " mov rcx, stdout_fd\n "
1996- " mov [rcx], rax\n "
1997- " mov rcx, -12 ; stderr fd\n "
1996+ " mov QWORD PTR [rip + stdout_fd], rax\n "
1997+ " mov rcx, -12 # stderr fd\n "
19981998 " call GetStdHandle\n "
1999- " mov rcx, stderr_fd\n "
2000- " mov [rcx], rax\n "
2001- " add rsp, 32 ; remove shadow space\n "
1999+ " mov QWORD PTR [rip + stderr_fd], rax\n "
2000+ " add rsp, 32 # remove shadow space\n "
20022001 " ret\n "
20032002 " \n "
2004- " ; rdx - buff, r8 - number of bytes -> rax - number written\n "
2003+ " # rdx - buff, r8 - number of bytes -> rax - number written\n "
20052004 " stdout_write:\n "
2006- " mov rcx, QWORD [rel stdout_fd]\n "
2005+ " mov rcx, QWORD PTR [rip + stdout_fd]\n "
20072006 " jmp write_file\n "
20082007 " stderr_write:\n "
2009- " mov rcx, QWORD [rel stderr_fd]\n "
2010- " ; fall through to write_file\n "
2008+ " mov rcx, QWORD PTR [rip + stderr_fd]\n "
2009+ " # fall through to write_file\n "
20112010 " \n "
2012- " ; rcx - fd, rdx - buff, r8 - chars / buffsize -> rax - number read/written\n "
2011+ " # rcx - fd, rdx - buff, r8 - chars / buffsize -> rax - number read/written\n "
20132012 " write_file:\n "
2014- " mov rax, WriteFile\n "
2013+ " lea rax, [rip + WriteFile] \n "
20152014 " jmp call_winapi_file_op\n "
20162015 " read_file:\n "
2017- " mov rax, ReadFile\n "
2016+ " lea rax, [rip + ReadFile] \n "
20182017 " call_winapi_file_op:\n "
2019- " mov rbp, rsp ; save rsp @ retval\n "
2020- " and rsp, -16 ; force 16-byte alignment\n "
2021- " push 0 ; number of bytes written/read var\n "
2022- " mov r9, rsp ; ptr to that var\n "
2023- " push 0 ; OVERLAPPED struct null ptr (5th arg) & still aligned\n "
2024- " sub rsp, 32 ; reserve shadow space\n "
2018+ " mov rbp, rsp # save rsp @ retval\n "
2019+ " and rsp, -16 # force 16-byte alignment\n "
2020+ " push 0 # number of bytes written/read var\n "
2021+ " mov r9, rsp # ptr to that var\n "
2022+ " push 0 # OVERLAPPED struct null ptr (5th arg) & still aligned\n "
2023+ " sub rsp, 32 # reserve shadow space\n "
20252024 " call rax\n "
2026- " add rsp, 32+8 ; remove shadow space & overlapped\n "
2027- " pop rax ; num written / read\n "
2025+ " add rsp, 32+8 # remove shadow space & overlapped\n "
2026+ " pop rax # num written / read\n "
20282027 " mov rsp, rbp\n "
20292028 " ret\n "
20302029 " stdin_read:\n "
2031- " mov rcx, stdin_fd ; get chars into stdin_buff\n "
2032- " mov rcx, [rcx]\n "
2033- " mov rdx, stdin_buff\n "
2034- " mov r8, STDIN_BUFF_SIZE\n "
2030+ " mov rcx, QWORD PTR [rip + stdin_fd] # get chars into stdin_buff\n "
2031+ " lea rdx, [rip + stdin_buff]\n "
2032+ " mov r8, OFFSET FLAT:STDIN_BUFF_SIZE\n "
20352033 " call read_file\n "
20362034 " \n "
2037- " mov rcx, stdin_buff_char_count ; store how many were read\n "
2038- " mov [rcx], rax\n "
2039- " mov rcx, stdin_buff_chars_read ; 0 chars were processed\n "
2040- " mov QWORD [rcx], 0\n "
2035+ " mov QWORD PTR [rip + stdin_buff_char_count], rax # store how many were read\n "
2036+ " mov QWORD PTR [rip + stdin_buff_chars_read], 0 # 0 chars were processed\n "
20412037 " ret\n "
20422038 " \n "
2043- " stdin_peek: ; returns next raw stdin char, does not advance read ptr -> rdx char\n "
2044- " mov rax, stdin_buff_char_count ; if (char_count == chars_read) fill the stdin_buff\n "
2045- " mov rcx, [rax]\n "
2046- " mov rax, stdin_buff_chars_read\n "
2047- " cmp rcx, [rax]\n "
2039+ " stdin_peek: # returns next raw stdin char, does not advance read ptr -> rdx char\n "
2040+ " mov rcx, QWORD PTR [rip + stdin_buff_char_count] # if (char_count == chars_read) fill the stdin_buff\n "
2041+ " mov rdx, QWORD PTR [rip + stdin_buff_chars_read]\n "
2042+ " cmp rcx, rdx\n "
20482043 " jne stdin_peek_valid\n "
20492044 " call stdin_read\n "
20502045 " stdin_peek_valid:\n "
2051- " mov rax, stdin_buff_chars_read ; char addr \n "
2052- " mov rcx, stdin_buff\n "
2053- " add rcx, [ rax] \n "
2046+ " mov rax, [rip + stdin_buff_chars_read] # chars read \n "
2047+ " lea rcx, [rip + stdin_buff] \n "
2048+ " add rcx, rax\n "
20542049 " \n "
2055- " xor rdx, rdx ; peek the char\n "
2050+ " xor rdx, rdx # peek the char\n "
20562051 " mov dl, [rcx]\n "
20572052 " ret\n "
2058- " get_next_char: ; gets next char from stdin (buffered), advances read ptr -> rdx char\n "
2059- " call stdin_peek ; peek the first unread char\n "
2060- " mov rax, stdin_buff_chars_read ; eat the char\n "
2061- " inc QWORD [rax]\n "
2053+ " get_next_char: # gets next char from stdin (buffered), advances read ptr -> rdx char\n "
2054+ " call stdin_peek # peek the first unread char\n "
2055+ " inc QWORD PTR [rip + stdin_buff_chars_read] # eat the char\n "
20622056 " ret\n "
20632057 " \n "
2064- " utos: ; n - rax -> r8 char count, r9 - char* str\n "
2065- " xor r8, r8 ; char count\n "
2066- " mov r9, stdout_buff+STDOUT_BUFF_SIZE-1 ; curr buff pos\n "
2067- " mov r10, 10 ; base\n "
2058+ " utos: # n - rax -> r8 char count, r9 - char* str\n "
2059+ " xor r8, r8 # char count\n "
2060+ " lea r9, [rip + stdout_buff+STDOUT_BUFF_SIZE-1] # curr buff pos\n "
2061+ " mov r10, 10 # base\n "
20682062 " utos_loop:\n "
20692063 " xor rdx, rdx\n "
20702064 " div r10\n "
@@ -2077,35 +2071,34 @@ void generate(ofstream& outFile, vector<Instr>& instrs) {
20772071 " cmp rax, 0\n "
20782072 " jne utos_loop\n "
20792073 " ret\n "
2080- " print_unsigned: ; rax - n -> rax - num written\n "
2074+ " print_unsigned: # rax - n -> rax - num written\n "
20812075 " call utos\n "
2082- " mov rdx, r9 ; str\n "
2076+ " mov rdx, r9 # str\n "
20832077 " call stdout_write\n "
20842078 " ret\n "
2085- " print_unsigned_err: ; rax - n -> rax - num written\n "
2079+ " print_unsigned_err: # rax - n -> rax - num written\n "
20862080 " call utos\n "
2087- " mov rcx, stderr_fd\n "
2088- " mov rcx, [rcx]\n "
2089- " mov rdx, r9 ; str\n "
2081+ " mov rcx, QWORD PTR [rip + stderr_fd]\n "
2082+ " mov rdx, r9 # str\n "
20902083 " call write_file\n "
20912084 " ret\n "
2092- " input_unsigned: ; consumes all numeric chars, constructs uint out of them -> rax num\n "
2093- " xor rax, rax ; out\n "
2085+ " input_unsigned: # consumes all numeric chars, constructs uint out of them -> rax num\n "
2086+ " xor rax, rax # out\n "
20942087 " input_unsigned_loop:\n "
20952088 " push rax\n "
2096- " call stdin_peek ; get next char\n "
2097- " sub rdx, '0' ; isdigit()\n "
2089+ " call stdin_peek # get next char\n "
2090+ " sub rdx, '0' # isdigit()\n "
20982091 " js input_unsigned_end\n "
20992092 " cmp rdx, 9\n "
21002093 " jg input_unsigned_end\n "
21012094 " push rdx\n "
21022095 " \n "
2103- " call get_next_char ; eat the valid char\n "
2104- " pop rcx ; add to parsed\n "
2096+ " call get_next_char # eat the valid char\n "
2097+ " pop rcx # add to parsed\n "
21052098 " pop rax\n "
21062099 " mov r10, 10\n "
21072100 " mul r10\n "
2108- " add rax, rcx ; rax = 10 * rax + rcx\n "
2101+ " add rax, rcx # rax = 10 * rax + rcx\n "
21092102 " \n "
21102103 " mov r10, 65535\n "
21112104 " cmp rax, r10\n "
@@ -2115,16 +2108,14 @@ void generate(ofstream& outFile, vector<Instr>& instrs) {
21152108 " pop rax\n "
21162109 " ret\n "
21172110 " \n "
2118- " global _start\n "
2111+ " . global _start\n "
21192112 " _start:\n "
2120- " ; initialization\n "
2113+ " # initialization\n "
21212114 " call get_std_fds\n "
2122- " mov rcx, stdin_buff_char_count\n "
2123- " mov QWORD [rcx], 0\n "
2124- " mov rcx, stdin_buff_chars_read\n "
2125- " mov QWORD [rcx], 0\n "
2115+ " mov QWORD PTR [rip + stdin_buff_char_count], 0\n "
2116+ " mov QWORD PTR [rip + stdin_buff_chars_read], 0\n "
21262117 " \n "
2127- " mov r13, cells\n "
2118+ " lea r13, QWORD PTR [rip + cells] \n "
21282119 " xor r14, r14\n "
21292120 " xor r15, r15\n "
21302121 " \n " ;
@@ -2133,47 +2124,50 @@ void generate(ofstream& outFile, vector<Instr>& instrs) {
21332124 for (int i = 0 ; i < instrs.size (); ++i) {
21342125 instr = instrs[i];
21352126 outFile << " instr_" << i << " :\n " ;
2136- outFile << " ; " << instr.toStr () << ' \n ' ;
2127+ outFile << " # " << instr.toStr () << ' \n ' ;
21372128 genAssembly (outFile, instr, i);
21382129 }
21392130 outFile <<
21402131 " instr_" << instrs.size () << " :\n "
21412132 " jmp end\n "
21422133 " \n "
2143- " ; runtime errors, expect instr number in rsi, errorneous value in rcx\n "
2134+ " # runtime errors, expect instr number in rsi, errorneous value in rcx\n "
21442135 " jmp_error:\n "
2145- " mov rdx, jmp_error_message\n "
2146- " mov r8, jmp_error_message_len\n "
2136+ " lea rdx, [rip + jmp_error_message] \n "
2137+ " mov r8, OFFSET FLAT: jmp_error_message_len\n "
21472138 " call error\n "
21482139 " \n "
21492140 " end:\n "
2150- " ; exit(0)\n "
2141+ " # exit(0)\n "
21512142 " mov rax, 0\n "
21522143 " call exit\n "
21532144 " \n "
2154- " section .bss\n "
2155- " cells: resw " << CELLS << " \n "
2156- " stdin_fd: resq 1\n "
2157- " stdout_fd: resq 1\n "
2158- " stderr_fd: resq 1\n "
2159- " stdout_buff: resb STDOUT_BUFF_SIZE\n "
2160- " stdin_buff_chars_read: resq 1\n "
2161- " stdin_buff_char_count: resq 1\n "
2162- " stdin_buff: resb STDIN_BUFF_SIZE\n "
2145+ " .bss\n "
2146+ " .balign 8\n "
2147+ " \n "
2148+ " cells: .skip 2 * " << CELLS << " # resw for memory\n "
2149+ " stdin_fd: .skip 8\n "
2150+ " stdout_fd: .skip 8\n "
2151+ " stderr_fd: .skip 8\n "
2152+ " stdout_buff: .skip STDOUT_BUFF_SIZE # resb\n "
2153+ " stdin_buff: .skip STDIN_BUFF_SIZE # resb\n "
2154+ " stdin_buff_chars_read: .skip 8\n "
2155+ " stdin_buff_char_count: .skip 8\n "
2156+ " \n "
2157+ " .data\n "
2158+ " .equ STDOUT_BUFF_SIZE, " << STDOUT_BUFF_SIZE << " \n "
2159+ " .equ STDIN_BUFF_SIZE, " << STDIN_BUFF_SIZE << " \n "
21632160 " \n "
2164- " section .data \n "
2165- " STDOUT_BUFF_SIZE: EQU " << STDOUT_BUFF_SIZE << " \n "
2166- " STDIN_BUFF_SIZE: EQU " << STDIN_BUFF_SIZE << " \n "
2161+ " # error messages \n "
2162+ " ERROR_template: .ascii \"\\ nERROR: instr_ \ "\n"
2163+ " .equ ERROR_template_len, . - ERROR_template \n "
21672164 " \n "
2168- " ; error messages\n "
2169- " ERROR_template: db 10,\" ERROR: instr_\"\n "
2170- " ERROR_template_len: EQU $-ERROR_template\n "
2171- " jmp_error_message: db \" : jmp destination out of bounds: \"\n "
2172- " jmp_error_message_len: EQU $-jmp_error_message\n "
2165+ " jmp_error_message: .ascii \" : jmp destination out of bounds: \"\n "
2166+ " .equ jmp_error_message_len, . - jmp_error_message\n "
21732167 " \n "
2174- " ; instruction addresses\n "
2175- " instruction_count: EQU " << instrs.size () << " \n "
2176- " instruction_offsets: dq " ;
2168+ " # instruction addresses\n "
2169+ " .equ instruction_count, " << instrs.size () << " \n "
2170+ " instruction_offsets: .quad " ;
21772171
21782172 outFile << " instr_0" ;
21792173 for (int i = 1 ; i <= instrs.size (); ++i) {
@@ -2304,17 +2298,18 @@ void removeFile(fs::path file) {
23042298}
23052299int compileAndRun (Flags& flags) {
23062300 runCmdEchoed ({
2307- " nasm" , " -fwin64" , " -g" , " -F cv8" ,
2308- flags.filePathStr (" asm" )
2301+ " gcc" , " -c" ,
2302+ " -o" , flags.filePathStr (" obj" ),
2303+ flags.filePathStr (" s" )
23092304 }, flags);
23102305 runCmdEchoed ({
23112306 " gcc" , " -nostartfiles" , " -Wl,-e,_start" , " -lkernel32" ,
23122307 " -o" , flags.filePathStr (" exe" ), " -g" , flags.filePathStr (" obj" )
23132308 }, flags);
23142309 if (flags.keepAsm ) {
2315- cout << " [NOTE] asm file: " << flags.filePath (" asm " ) << " :183:1\n " ;
2310+ cout << " [NOTE] asm file: " << flags.filePath (" s " ) << " :183:1\n " ;
23162311 } else {
2317- removeFile (flags.filePath (" asm " ));
2312+ removeFile (flags.filePath (" s " ));
23182313 }
23192314 removeFile (flags.filePath (" obj" ));
23202315 if (flags.run ) return runCmdEchoed ({flags.filePathStr (" exe" )}, flags, false );
@@ -2330,7 +2325,7 @@ void run(Flags& flags) {
23302325 globalVm = VM ();
23312326 interpret ();
23322327 } else {
2333- ofstream outFile = openOutputFile (flags.filePath (" asm " ));
2328+ ofstream outFile = openOutputFile (flags.filePath (" s " ));
23342329 generate (outFile, parseCtx.instrs );
23352330
23362331 exitCode = compileAndRun (flags);
0 commit comments