in theory all that's left for program 02 is filling in jumps

This commit is contained in:
pommicket 2021-09-02 12:12:55 -04:00
parent 336a793149
commit 447e8e2796
5 changed files with 472 additions and 3 deletions

View file

@ -41,7 +41,7 @@ So, for example, the `sy` command outputs a syscall instruction. You can see
`||` is a very important command. It outputs an ELF header for our executable. `||` is a very important command. It outputs an ELF header for our executable.
Rather than compute the correct size of the file, it just sets the "file size" Rather than compute the correct size of the file, it just sets the "file size"
and "memory size" members of the program header to `0x40000` (enough for a 256KB and "memory size" members of the program header to `0x80000` (enough for a 512KB
executable). As it turns out, Linux won't mind if the program header lies about executable). As it turns out, Linux won't mind if the program header lies about
how much data is in the file. how much data is in the file.

View file

@ -16289,6 +16289,6 @@ cc cc cc cc cc cc cc cc
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 40 00 00 00 00 00 00 00 40 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 03 00 00 00 00 00 00 00 08 00 00 00 00 00
00 00 03 00 00 00 00 00 00 00 08 00 00 00 00 00
00 10 00 00 00 00 00 00 00 10 00 00 00 00 00 00

2
02/Makefile Normal file
View file

@ -0,0 +1,2 @@
out01: in01
../01/out00

445
02/in01 Normal file
View file

@ -0,0 +1,445 @@
|| ELF Header
;jm;50;00;00;00 jump over data to code
;'i;'n;'0;'2;00 (0x40007d) input filename
;'o;'u;'t;'0;'2;00 (0x400082) output filename
;00;00;' ;'n;'o;'t;' ;'r;'e;'c;'o;'g;'n;'i;'z;'e;'d;\n;00;00;00;00;00;00 (0x400088) error message/where we read to
;48;b8;00 (0x4000a0) load immediate instruction
;00;00;00;00;00
;00;00;00;00;00;00;00;00 (0x4000a8) used for output
;00;00;' ;'b;'a;'d;' ;'l;'a;'b;'e;'l;\n;00 (0x400090)
;00;00;' 'b;'a;'d;' ;'n;'u;'m;'b;'e;'r;\n;00 (0x40009e)
;00
;im;7d;00;40;00;00;00;00;00 pointer to input filename
;JA
;zA O_RDONLY
;IA
;im;02;00;00;00;00;00;00;00 syscall 2, open
;sy
;im;82;00;40;00;00;00;00;00 pointer to output filename
;JA
;im;41;02;00;00;00;00;00;00 O_WRONLY | O_CREAT | O_TRUNC
;IA
;im;ed;01;00;00;00;00;00;00 0o755
;DA
;im;02;00;00;00;00;00;00;00 open
;sy
begin by writing the elf header.
the segment we're loading in includes the ELF header at address 0x400000, so we can just read it from there
;im;04;00;00;00;00;00;00;00 out fd
;JA
;im;00;00;40;00;00;00;00;00 pointer to ELF header
;IA
;im;78;00;00;00;00;00;00;00 length of ELF header
;DA
;im;01;00;00;00;00;00;00;00 write
;sy
-- read command --
;im;03;00;00;00;00;00;00;00 input file descriptor
;JA
;im;88;00;40;00;00;00;00;00 where to read to
;IA
;im;02;00;00;00;00;00;00;00 read 2 bytes
;DA
;zA read
;sy
;BA
;im;02;00;00;00;00;00;00;00
;jg;cd;cd;cd;cd end of file
calculate the index in the command table
;im;88;00;40;00;00;00;00;00
;BA
;zA;lb
;<I;07
;CA
;im;89;00;40;00;00;00;00;00
;BA
;zA;lb
;BC
;+B
;RA store it away in rbp
;BA
let's check if it's a label definition
;im;3a;1d;00;00;00;00;00;00
;cm
;jn;cd;cd;cd;cd skip label definition handling code
it's a label definition. first, let's get the position in the file.
we can do this with the lseek syscall.
it can be used to move to a different point in the file, but it can also be
used to get the current file offset, in bytes
;im;04;00;00;00;00;00;00;00 fd
;JA
;zA;IA don't move
;im;01;00;00;00;00;00;00;00 SEEK_CUR (use the current position)
;DA
;im;08;00;00;00;00;00;00;00 lseek
;sy
our offset is now in rax. let's add the base address,
then store the label address away in rbp
;BA
;im;00;00;40;00;00;00;00;00
;+B
;RA
read 2-byte label name
;im;03;00;00;00;00;00;00;00 input fd
;JA
;im;88;00;40;00;00;00;00;00
;IA
;im;02;00;00;00;00;00;00;00
;DA
;zA
;sy
get the address of the entry in the label table
;im;88;00;40;00;00;00;00;00
;BA
;zA;lb
;<I;07
;CA
;im;89;00;40;00;00;00;00;00
;BA
;zA;lb
;BC
;+B
;BA
;im;00;00;43;00;00;00;00;00 label table offset = 0x430000
;+B
okay now let's write the current address there
;BA
;AR
;sq
;00;00;00;00;00;00;00;00;00;00;00;00;00;00;00;00 unused padding
;00;00;00;00;00;00;00;00;00;00;00;00;00;00;00;00 unused padding
;jm;cd;cd;cd;cd skip to newline
okay it's not a label definition. let's look at the command table
;AB
;<I;03
;BA
;im;00;00;41;00;00;00;00;00 command table offset = 0x410000
;+B
;BA
;zA;lb
check if there's anything there
;te
;jn;cd;cd;cd;cd
okay there's nothing there. that's not good. let's print our error message.
;im;02;00;00;00;00;00;00;00 stderr
;JA
;im;88;00;40;00;00;00;00;00 error message
;IA
;im;12;00;00;00;00;00;00;00 length
;DA
;im;01;00;00;00;00;00;00;00 write
;sy
okay there *is* something here.
;DA
;im;01;00;00;00;00;00;00;00 add 1 to address to skip over length
;+B
;IA
;im;04;00;00;00;00;00;00;00 fd
;JA
;im;01;00;00;00;00;00;00;00 write
;sy
now let's check if it's a special instruction, i.e. im or a jump instruction
;BR
;im;ed;34;00;00;00;00;00;00
;cm
;jn;cd;cd;cd;cd jump over "im" handling code
read two bytes:
;im;03;00;00;00;00;00;00;00
;JA
;im;9e;00;40;00;00;00;00;00
;IA
;im;02;00;00;00;00;00;00;00
;DA
;zA
;sy
now look at the second byte (the first one should be a space):
;im;9f;00;40;00;00;00;00;00
;BA
;zA
;lb
;BA
;im;3a;00;00;00;00;00;00;00
;cm
;jn;cd;cd;cd;cd
It's a :. Let's look at the label.
Read 2 bytes.
;im;03;00;00;00;00;00;00;00
;JA
;im;90;00;40;00;00;00;00;00
;IA
;im;02;00;00;00;00;00;00;00
;DA
;zA
;sy
Now find the entry in the label table.
;im;90;00;40;00;00;00;00;00
;BA
;zA;lb
;<I;07
;CA
;im;91;00;40;00;00;00;00;00
;BA
;zA;lb
;BC
;+B
;<I;03
;BA
;im;00;00;43;00;00;00;00;00 Offset of label table = 0x430000
;+B
;BA
;zA
;lq
;te check if there's anything there
;jn;cd;cd;cd;cd
oh no there's nothing there
;im;02;00;00;00;00;00;00;00 stderr
;JA
;im;90;00;40;00;00;00;00;00 bad label error message
;IA
;im;0a;00;00;00;00;00;00;00 length
;DA
;im;01;00;00;00;00;00;00;00 write
;sy
;im;01;00;00;00;00;00;00;00 exit code
;JA
;im;3c;00;00;00;00;00;00;00 exit
;sy
okay let's output what's at that label
;BA
;im;a8;00;40;00;00;00;00;00
;xc
;sq
;IB pointer to data
;im;04;00;00;00;00;00;00;00 file descriptor
;JA
;im;08;00;00;00;00;00;00;00 length
;DA
;im;01;00;00;00;00;00;00;00 write
;sy
;jm;cd;cd;cd;cd skip to newline
okay it's not a label
let's check if it's hexadecimal
;im;78;00;00;00;00;00;00;00 ascii 'x'
;cm
;jne;cd;cd;cd;cd
it's hexadecimal. we'll use rcx to store the number
;zA;CA
;im;03;00;00;00;00;00;00;00 input fd
;JA
;im;88;00;40;00;00;00;00;00
;IA
;im;01;00;00;00;00;00;00;00 read 1 byte at a time
;DA
;zA read
;sy
;im;88;00;40;00;00;00;00;00
;BA
;zA;lb
;BA
;im;30;00;00;00;00;00;00;00
;jl;cd;cd;cd;cd end of number
;im;39;00;00;00;00;00;00;00
;jg;cd;cd;cd;cd end of number
okay it's one of 0-9
;im;d0;ff;ff;ff;ff;ff;ff;ff
;+B
;BA
;AC
;<I;04
;+B
;CA
;jm;cd;cd;cd;cd jump back to read the next digit
;00;00;00;00;00;00;00;00;00;00;00;00;00;00;00;00 unused padding
check if it's a-f
;im;61;00;00;00;00;00;00;00
;jl;cd;cd;cd;cd end of number
;im;66;00;00;00;00;00;00;00
;jg;cd;cd;cd;cd end of number
okay it is
;im;a9;ff;ff;ff;ff;ff;ff;ff
;+B
;BA
;AC
;<I;04
;+B
;CA
;jm;cd;cd;cd;cd jump back to read the next digit
;00;00;00;00;00;00;00;00;00;00;00;00;00;00;00;00 unused padding
it's not hexadecimal, let's check if it's decimal
;im;64;00;00;00;00;00;00;00
;cm
;jne;cd;cd;cd;cd bad number
it's decimal. we'll use rcx to store the number
;zA;CA
;im;03;00;00;00;00;00;00;00 input fd
;JA
;im;88;00;40;00;00;00;00;00
;IA
;im;01;00;00;00;00;00;00;00 read 1 byte at a time
;DA
;zA read
;sy
;im;88;00;40;00;00;00;00;00
;BA
;zA;lb
;BA
check if it's 0-9
;im;30;00;00;00;00;00;00;00
;jl;cd;cd;cd;cd end of number
;im;39;00;00;00;00;00;00;00
;jg;cd;cd;cd;cd end of number
okay it is
;im;d0;ff;ff;ff;ff;ff;ff;ff
;+B
;DA store digit away in rdx
;im;0a;00;00;00;00;00;00;00
;BC
;+*
;BD return digit to rbx
;+B
;CA
;jm;cd;cd;cd;cd next digit
;00;00;00;00;00;00;00;00;00;00;00;00;00;00;00;00 unused padding
--- end of number ---
the number will be in rcx
;im;a8;00;40;00;00;00;00;00 this is where we'll put the number
;BA
;AC
;sq
now write it to the file
;im;04;00;00;00;00;00;00;00
;JA
;im;a8;00;40;00;00;00;00;00
;IA
;im;08;00;00;00;00;00;00;00
;DA
;im;01;00;00;00;00;00;00;00
;sy
;jm;cd;cd;cd;cd skip to newline
;00;00;00;00;00;00;00;00;00;00;00;00;00;00;00;00 unused padding
--- bad number ---
;im;02;00;00;00;00;00;00;00 stderr
;JA
;im;9e;00;40;00;00;00;00;00 bad number error message
;IA
;im;0b;00;00;00;00;00;00;00 length
;DA
;im;01;00;00;00;00;00;00;00 write
;sy
;im;01;00;00;00;00;00;00;00 exit code
;JA
;im;3c;00;00;00;00;00;00;00 exit
;sy
;00;00;00;00;00;00;00;00;00;00;00;00;00;00;00;00 unused padding
okay it's not an im instruction. let's check if it's a jump instruction
;AR
;>I;07
;BA
;im;6a;00;00;00;00;00;00;00
;cm
;jn;cd;cd;cd;cd skip to newline
it is a jump instruction. let's read in the label and write it to--
wait a minute! this is just like our immediate label code. let's just
read the space between the command and the label, and then jump there
;im;03;00;00;00;00;00;00;00
;JA
;im;88;00;40;00;00;00;00;00
;IA
;im;01;00;00;00;00;00;00;00
;DA
;zA
;sy
;jm;cd;cd;cd;cd
;00;00;00;00;00;00;00;00;00;00;00;00;00;00;00;00 unused padding
;00;00;00;00;00;00;00;00;00;00;00;00;00;00;00;00 unused padding
-- skip to newline --
read 1 byte into 0x400088
;im;03;00;00;00;00;00;00;00
;JA
;im;88;00;40;00;00;00;00;00
;IA
;im;01;00;00;00;00;00;00;00
;DA
;sy
;im;88;00;40;00;00;00;00;00
;BA
;zA;lb;BA
;im;0a;00;00;00;00;00;00;00
;cm
;jn;cd;cd;cd;cd go back to the start of "skip to newline"
;jm;cd;cd;cd;cd go all the way back and read the next two-byte command
;00;00;00;00;00;00;00;00;00;00;00;00;00;00;00;00 unused padding
;00;00;00;00;00;00;00;00;00;00;00;00;00;00;00;00 unused padding
;00;00;00;00;00;00;00;00;00;00;00;00;00;00;00;00 unused padding
;00;00;00;00;00;00;00;00;00;00;00;00;00;00;00;00 unused padding
-- end of file --
;zA;JA exit code 0
;im;3c;00;00;00;00;00;00;00 exit
;sy
;cc
;

22
02/in02 Normal file
View file

@ -0,0 +1,22 @@
im d2
JA
im :hw
IA
im d14
DA
sy
::hw
'H
'e
'l
'l
'o
'
'w
'o
'r
'l
'd
'!
\n