From 6602c82f9f35235b998132f0adc54c852aa4e025 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Mon, 16 Jul 2018 22:18:18 -0700 Subject: 4363 - subx: first program using the stack segment We allocate space for a local variable, read() a character from stdin to it, and write() it out to stdout. --- subx/010vm.cc | 4 ++++ subx/019syscalls.cc | 2 ++ subx/020elf.cc | 7 ++++--- subx/ex5 | Bin 0 -> 138 bytes subx/ex5.subx | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 subx/ex5 create mode 100644 subx/ex5.subx diff --git a/subx/010vm.cc b/subx/010vm.cc index 17c4e064..50074114 100644 --- a/subx/010vm.cc +++ b/subx/010vm.cc @@ -133,6 +133,7 @@ void run_one_instruction() { // End Two-Byte Opcodes Starting With 0f default: cerr << "unrecognized second opcode after 0f: " << HEXBYTE << NUM(op2) << '\n'; + DUMP(""); exit(1); } break; @@ -144,16 +145,19 @@ void run_one_instruction() { // End Three-Byte Opcodes Starting With f3 0f default: cerr << "unrecognized third opcode after f3 0f: " << HEXBYTE << NUM(op3) << '\n'; + DUMP(""); exit(1); } break; default: cerr << "unrecognized second opcode after f3: " << HEXBYTE << NUM(op2) << '\n'; + DUMP(""); exit(1); } break; default: cerr << "unrecognized opcode: " << HEXBYTE << NUM(op) << '\n'; + DUMP(""); exit(1); } } diff --git a/subx/019syscalls.cc b/subx/019syscalls.cc index f9698957..81040d4e 100644 --- a/subx/019syscalls.cc +++ b/subx/019syscalls.cc @@ -1,5 +1,6 @@ :(before "End Single-Byte Opcodes") case 0xcd: { // int imm8 (software interrupt) + trace(2, "run") << "syscall" << end(); uint8_t code = next(); if (code != 0x80) { raise << "Unimplemented interrupt code " << HEXBYTE << code << '\n' << end(); @@ -17,6 +18,7 @@ void process_int80() { exit(/*exit code*/Reg[EBX].u); break; case 3: + DUMP(""); Reg[EAX].i = read(/*file descriptor*/Reg[EBX].u, /*memory buffer*/mem_addr_u8(Reg[ECX].u), /*size*/Reg[EDX].u); break; case 4: diff --git a/subx/020elf.cc b/subx/020elf.cc index 88de65fd..85bda201 100644 --- a/subx/020elf.cc +++ b/subx/020elf.cc @@ -4,6 +4,7 @@ :(before "End Main") assert(argc > 1); if (is_equal(argv[1], "run")) { + START_TRACING_UNTIL_END_OF_SCOPE; assert(argc > 2); reset(); cerr << std::hex; @@ -59,9 +60,9 @@ void load_elf_contents(uint8_t* elf_contents, size_t size) { for (size_t i = 0; i < e_phnum; ++i) load_segment_from_program_header(elf_contents, size, e_phoff + i*e_phentsize, e_ehsize); - // TODO: need to set up real stack somewhere - - Reg[ESP].u = Reg[EBP].u = End_of_program; + // initialize code and stack + Reg[ESP].u = AFTER_STACK; + Reg[EBP].u = 0; EIP = e_entry; } diff --git a/subx/ex5 b/subx/ex5 new file mode 100644 index 00000000..536ddcd6 Binary files /dev/null and b/subx/ex5 differ diff --git a/subx/ex5.subx b/subx/ex5.subx new file mode 100644 index 00000000..f7411939 --- /dev/null +++ b/subx/ex5.subx @@ -0,0 +1,47 @@ +## read a character from stdin, save it to a local on the stack, write it to stdout + +== 0x08048054 # code segment, after leaving room for ELF header and segment headers +# opcode ModR/M SIB displacement immediate +# instruction mod, reg, Reg/Mem bits scale, index, base +# 1-3 bytes 0/1 byte 0/1 byte 0/1/2/4 bytes 0/1/2/4 bytes + +## function main + # prolog + 55 # push EBP + 89 e5 # copy ESP to EBP + # ModR/M: 11 (direct mode) 100 (src ESP) 101 (dest EBP) + # allocate x on the stack + 81 ec 4/imm32 # subtract 4 bytes from ESP + # ModR/M: 11 (direct mode) 101 (subtract imm32) 100 (dest EBP) + + ## read(stdin, x, 1) + # fd = 0 (stdin) + bb 0/imm32 # copy 0 to EBX + # set location to read character to + 89 e9 # copy EBP to ECX + # ModR/M: 11 (direct mode) 101 (src EBP) 001 (dest ECX) + # size = 1 character + ba 1/imm32 # copy 1 to EDX + # syscall = read + b8 3/imm32 # copy 3 to EAX + # call + cd 128/imm8 # int 80h + + ## write(stdout, x, 1) + # fd = 1 (stdout) + bb 1/imm32 # copy 1 to EBX + # set location of character to write out + 89 e9 # copy EBP to ECX + # ModR/M: 11 (direct mode) 101 (src EBP) 001 (dest ECX) + # size = 1 character + ba 1/imm32 # copy 1 to EDX + # syscall = write + b8 4/imm32 # copy 4 to EAX + # call + cd 128/imm8 # int 80h + + ## exit(EBX) + b8 1/imm32 # copy 1 to EAX + cd 128/imm8 # int 80h + +# vim:ft=subx:nowrap -- cgit 1.4.1-2-gfad0