[video member=pervognsen stream_platform=twitch project=bitwise title="More Assembler Hacking" vod_platform=youtube id=_6zAlm0Edrw annotator=Miblo] [0:00][Recap and set the stage for the day, with a mention of the pacing of the stream][:speech] [1:58][Pull our test :asm out into a multi-line string] [2:54][:Run it to see that it didn't work] [3:18][Allow parse_line() to optionally match a \\n at the beginning][:parsing] [3:46][:Run it and show the :emulation in action][:asm :parsing] [4:05][Define other data types and helper commands in the cmd_defs table, introducing cmd_org() and cmd_align()][:asm :"code generation"] [7:19][Test creation of a uint8][:asm :"code generation"] [8:44][:Run it to see how the emulator handles our uint8][:asm :"code generation" :emulation] [9:57][Introduce cmd_fill()[ref site="GNU Binutils" page="7.33 .fill repeat , size , value" url=https://sourceware.org/binutils/docs-2.28/as/Fill.html]][:asm :"code generation"] [15:26][Test our fill command, enabling cmd_fill() to handle commas][:asm :"code generation"] [17:27][:Run it and hit an "Expected instruction" error][:asm :"code generation"] [18:07][Add fill to the cmd_defs table, and add :"error handling" to cmd_fill()][:asm :"code generation"] [20:40][:Run it to see our fill in action][:asm :"code generation" :emulation] [21:04][Do a test of placing a variable at a specific position using org rather than fill][:asm :"code generation"] [22:17][:Run it to see this in action, and explain why it works][:asm :"code generation" :emulation] [22:45][@rygorous][@pervognsen Your cmd_uint16() is buggy (it does uint8 only)][:asm :"code generation"] [22:50][Fix cmd_uint16() to call asm_uint16()][:asm :"code generation"] [23:04][Begin to enable parse_instr() to handle store instructions[ref author="Andrew Waterman and Krste Asanović" title="The RISC-V Instruction Set Manual - Volume 1: User-Level ISA" url=https://github.com/riscv/riscv-isa-manual/blob/master/release/riscv-spec-v2.2.pdf]][:asm :isa] [24:45][Two variants of load][:asm :isa :speech] [26:09][@rygorous][Most RISCs do have "store , ()" though][:isa] [26:30][Enable parse_instr() to handle both the register- and label-based load instruction][:asm :"code generation"] [31:05][Test a register-based load][:asm :"code generation"] [31:59][:Run it and hit an "Immediate is out of range" error][:asm :"code generation" :emulation] [32:55][Reduce the offset in our addi instruction][:asm] [33:00][:Run it to see that it works][:asm :"code generation" :emulation] [33:07][Test parenthesised offset in our lw instruction][:asm :"code generation"] [33:13][:Run it to see that it works][:asm :"code generation" :emulation] [33:16][Try changing that offset to our lw instruction, also editing the org instruction to match][:asm :"code generation"] [33:23][:Run it to see that this works too][:asm :"code generation" :emulation] [33:40][@miotatsu][I wasn't a fan of the store syntax when I first encountered it in RISC-V :asm either] [34:18][Introduce cmd_li() adding li to the cmd_defs table][:asm :"code generation"] [36:43][Test an li instruction][:asm :"code generation"] [36:50][:Run it and hit an "Immediate is out of range" error][:asm :"code generation" :emulation] [37:13][Fix cmd_li() to correctly emit our immediate][:asm :"code generation"] [37:43][:Run it to see that li works][:asm :"code generation" :emulation] [37:49][Enable cmd_li() to handle full-width immediates][:asm :"code generation"] [38:41][Test loading a big immediate][:asm :"code generation"] [39:00][:Run it to see that it works][:asm :"code generation" :emulation] [39:48][Enable parse_instr() to handle store instructions][:asm :parsing] [43:37][Test a sw instruction][:asm :"code generation"] [44:34][:Run it to see that the sw instruction works][:asm :"code generation" :emulation] [45:20][A few thoughts on x86 deference syntax][:isa :speech] [46:50][Introduce parse_addr() for parse_instr() to call, changing our load instruction to use the '\[' and '\]' syntax][:asm :parsing] [54:16][Test our \[ / \] syntax][:asm :parsing] [54:31][:Run it to see that it works][:asm :emulation :parsing] [54:38][Switch the store handling to use '\[' and '\]'][:asm :parsing] [56:06][:Run it to see that it works][:asm :emulation :parsing] [56:41][Further test our notation][:asm :parsing] [57:00][:Run it to see that it works][:asm :emulation :parsing] [57:42][Enable parse_instr() to handle the label-based store instruction][:asm :"code generation"] [59:44][Test a label-based store][:asm :"code generation"] [1:00:13][:Run it to see that it works][:asm :"code generation" :emulation] [1:00:31][@rygorous][Looking SPARC-y now! Well, halfway between SPARC and ARM. (This is why MIPS has the "at" register, "assembler temporary")][:isa] [1:01:57][Enable parse_instr() to handle branches,[ref author="Andrew Waterman and Krste Asanović" title="The RISC-V Instruction Set Manual - Volume 1: User-Level ISA" url=https://github.com/riscv/riscv-isa-manual/blob/master/release/riscv-spec-v2.2.pdf] introducing parse_label()][:asm :"code generation" :parsing] [1:07:26][Enable parse_instr() to handle jump and link, introducing cmd_jmp()][:asm :"code generation" :parsing] [1:12:27][Test branching and jumping][:asm :"code generation" :parsing] [1:13:15][Enable scan_int() to handle negative numbers][:parsing] [1:15:23][:Run it to see that it all works][:asm :"code generation" :emulation] [1:16:17][Test the j instruction][:asm :"code generation"] [1:16:41][:Run it and hit a "Jump target is out of range" error][:asm :"code generation" :emulation] [1:18:16][Fix cmd_jump() to use the offset][:asm :"code generation"] [1:18:23][:Run it to see that it works][:asm :"code generation" :emulation] [1:18:30][Rewrite the :asm test to perform the check after one iteration][:"code generation"] [1:19:53][:Run it to see that it works][:asm :"code generation" :emulation] [1:20:25][@elavid][But you know statically that the first check will go the loop since you just loaded x1 and x2][:asm] [1:20:42][Try an addi based on user input][:asm :"code generation" :"input handling"] [1:23:26][:Run it to see that it works][:asm :"code generation" :emulation :"input handling"] [1:24:47][Enable parse_instr() to handle the jalr instruction][:asm :"code generation" :parsing] [1:28:37][Introduce cmd_jmp_reg(), cmd_call() and cmd_ret() to handle the jr, call and ret instructions[ref author="Andrew Waterman and Krste Asanović" title="The RISC-V Instruction Set Manual - Volume 1: User-Level ISA" url=https://github.com/riscv/riscv-isa-manual/blob/master/release/riscv-spec-v2.2.pdf]][:asm :"code generation"] [1:34:47][@jgomes83][@pervognsen Line 985: && instead of <=] [1:34:55][Finish implementing cmd_ret()][:asm :"code generation"] [1:35:38][Test our call and return capabilities, doing a mul routine][:asm :"code generation"] [1:38:49][:Run it and hit an "Expected name, got newline" error][:asm :"code generation"] [1:40:05][Remove a comment from our test :asm] [1:40:11][:Run it to determine that there's a lexer bug in comment :parsing] [1:40:20][Test multiplication of user-input values][:asm :"code generation"] [1:41:39][:Run it and try our user-input multiplication][:asm :"code generation" :emulation :"input handling"] [1:44:49][Enable parse_instr() to handle lui (load upper immediate)][:asm :"code generation"] [1:45:32][:Run it to see that it works][:asm :"code generation" :emulation] [1:46:14][Q&A][:speech] [1:46:49][Reflect on our assembler, with a glimpse into the future of supporting constant expressions and local labels][:asm :speech] [1:51:32][That's it for today][:speech] [/video]