Dynamically changing machine code list size
Posted by dummythiccums@reddit | learnprogramming | View on Reddit | 3 comments
Hi all,
Tricky question about a a project in machine code, effectively Assembly code without labels. We are trying to find the length of a list that will change each time. The problem is, without labels, we can't change the PC offset dynamically to step back the correct amount in the memory to start iterating through the list. I'll provide the code below:
0011 0000 0000 0000 ; Starting memory location 0000 0000 0100 0011 ; List items, also below 0000 0000 0110 1110 0000 0000 0110 1011 0000 0000 0110 1101 0000 0000 0100 1111 0000 0000 0101 1110 0000 0000 0110 0011 0000 0000 0000 0000
1110011111110111 ; LEA R3, #-10 0101010010100000 ; AND R2, R2, #0
0110001011000000 ; LDR, R1, R3, #0 0000010000000110 ; BRz, #-7 0001001001000010 ; ADD R1, R1, R2 0001000001100000 ; ADD R0, R1, #0 1111000000100001 ; OUT 0001010010100001 ; ADD R2, R2, #1 0001011011100001 ; ADD R3, R3, #1 0000101111111000 ; BRnp #-8
1111000000100101 ; Halt
This code should take a list and: -Initialize index to zero For each data value: -Add index to the value -Output the resulting sum as an ASCII character -Increment index -Repeat for the next data value until the terminating value is reached -Halt the program
This works, the problem is, on the line "BRz #-7" we need the #-7 to change dynamically based on the size of the list initally loaded in. Any thoughts, ideas, or solutions are greatly appreciated!
roger_ducky@reddit
Got a free register? Increment that when you add an item?
Or, if you just, do it the “traditional programming language” way: * Move SP to store counter * update value at SP as you determine list size. * Use value at SP to go back. * Move SP back to where it was before.
CodeTinkerer@reddit
There are several assembly languages, not just one. Fortunately, with AI, I found the one you're referring to.
https://www.yorku.ca/sychen/research/LMC/LMCInstructions.html
LMC is Little Man Computer, which appears to be a minimalist assembly used for education purposes devised in the mid 1960s (there's a Wikipedia article). It only has 9 instructions while real world assembly tends to have maybe 100 instructions and some, significantly more.
In particular, the command BRz is "branch if the value of the accumulator is zero to an absolute address". Normally, there's a branch that depends on a register, but when you have an accumulator, you basically have two registers: the accumulator to compute stuff and the PC which is the address of the currently executing instruction. The BRz looks at an accumulator, checks if it's zero, and sets the PC to the hardcoded label or address if it is zero, causing the PC to do something besides incrementing up to run the next instruction in memory.
MIPS, an actual assembly language, has a similar branch instruction which does relative branches but has more flexibility (because it supports 32 registers, instead of 1 accumulator), but it's still a fixed offset to PC like LMC. It does, however, have a JR command which is jump register which loads the PC with the contents of the register, so you could branch to a 'jr` command and the register would contain this word size as a kind of variable.
OK turns out you're not using LMC but a variant called LC-3 which has 8 registers instead of an accumulator.
The commands include
BRz
as mentioned earlier that still behaves the same, but there is alsoBR
which is what MIPS calls a jump command. Branch commands typically test a register (or two) and jump relative to some address (in this case, it tests if a register has the value 0 and jumps if it does).A jump command does not test a register. However, LC-3 says the
br
command is an unconditional branch, so it behaves like a branch.If you were to write it in pseudocode, you want it to do something like
L1: BR Y # Y would jump based on a different word size
Basically, you're trying to implement something like
MIPS would allow this to be easier by using a
jr
command where the register could contain the size, but you have to construct an assembly version of if-else and possibly more than one if-else.At least, that's the idea that comes to mind.
Here's a sample LC-3 program: https://github.com/dideler/LC-3-Programs/blob/master/characterCounter.asm
Here's Wikipedia on it: https://en.wikipedia.org/wiki/Little_Computer_3
I would look at sample LC-3 code for implementing something like if-else to get you started.
teraflop@reddit
This looks like LC-3 assembly code, right?
First of all, your machine code doesn't match your assembly code. The binary instruction
0000010000000110
isBRz #6
(i.e. a jump to the HALT instruction at the end of the program), notBRz #-7
.Secondly, it doesn't make any sense to change the target of a conditional branch based on your data. Regardless of how long the list is, the distance from the branch to its target will be the same, so the branch offset will be the same.
Maybe you instead meant to ask about the operand of the
LEA
instruction that loads the address of the start of the list? If you're using an actual LC-3 assembler, you can define a label that points to the start of the list. When you refer to the label, the assembler will automatically compute the PC-relative offset from whatever instruction you're writing.If you're writing machine code by hand, you're doing the job of the assembler yourself, so you have to compute the offset yourself.