Prototyping ASM in a higher level language
Posted: Tue May 11, 2021 1:39 pm
Hi All,
Instead of "help me" I thought I would make a thread on prototyping asm in higher level languages. I write in lua and nasm. My nasm skills may not be the best, but I enjoy writing in assembly, that is until it doesn't work. Unfortuantely, with asm anything that goes wrong is my fault, so I have used a certain measure of prototype code in lua that does the same thing in a similar way. I wrote a routine to get a hexadecimal number from the user and store the result in rax.
Since the function complained of invalid input given valid input, I decided to rewrite it in lua.
The problem is my lua code works but my asm doesn't. (I am not trying to use lua for osdev, just for debugging.) This shows me that my lua prototype isn't acurrite enough. I am sure the problem with my NASM is simple, and after some good debugging, I should be able to get to the root of the problem, like with the rest of the problems I have fixed.
Here are both snippets of code. Take a deep breath, my ASM is not the best.
And here is my Lua prototype:
When I type valid HEX in, I get the INVALID HEX message.
My function doesn't get past the jl directive at the cmp al, '0'.
For my assembly, I should mention that READLN and WRITELN are both tested functions that work. READLN gets keys from the user, and stores the resulting string at address rbx placing a NULL at the end, when the user presses enter. (the LF is not saved in memory) This has been confirmed working.
WRITELN also works, it takes a rsi at a specified address, and prints the string to video memory.
Finally, I should mention that characters 80h to 85h are special characters that I also want to be able to use with hexadecimal.
So here is my question, Since my Lua code works, and my ASM does not, I am not accuritely representing asm in lua.
What are some tips to better prototype asm?
I see several problems with my current approach:
TL;DR:
My ASM was okay, but there was a memory problem, that the prototype code didn't detect.
What are some tips for prototyping asm in a higher level language?
When, if ever should this be done?
And finally, how useful is prototyping in debugging?
Instead of "help me" I thought I would make a thread on prototyping asm in higher level languages. I write in lua and nasm. My nasm skills may not be the best, but I enjoy writing in assembly, that is until it doesn't work. Unfortuantely, with asm anything that goes wrong is my fault, so I have used a certain measure of prototype code in lua that does the same thing in a similar way. I wrote a routine to get a hexadecimal number from the user and store the result in rax.
Since the function complained of invalid input given valid input, I decided to rewrite it in lua.
The problem is my lua code works but my asm doesn't. (I am not trying to use lua for osdev, just for debugging.) This shows me that my lua prototype isn't acurrite enough. I am sure the problem with my NASM is simple, and after some good debugging, I should be able to get to the root of the problem, like with the rest of the problems I have fixed.
Here are both snippets of code. Take a deep breath, my ASM is not the best.
Code: Select all
GETHEX:
push rsi
push rbx
.HEXREAD:
mov rbx, 0x200000
mov rsi, rbx
call READLN
xor rbx, rbx
.loadchar: ;while i < #m200000 do
lodsb
xor al, 0
jz .end
cmp al, '0'
jl .fail
cmp al, '9'
jg .net1
sub al, '0'
jmp .save
.net1:
cmp al, 'A'
jl .fail
cmp al, 'F'
jg .net2
sub al, 'A'
add al, 10
jmp .save
.net2:
cmp al, 80h
jl .fail
cmp al, 85h
jg .fail
sub al, 80h
add al, 10
jmp .save
.end:
mov rax, rbx
pop rbx
pop rsi
ret
.save:
shl rbx, 4
or bl, al
jmp .loadchar
.fail:
;print something
mov rsi, TEXT.FAIL
call WRITELN
jmp .HEXREAD
TEXT:
.FAIL: "FAILED TO PARSE HEX",0
Code: Select all
function hexread()
-- lua equivalent for debugging.
io.write("0x")
local m200000 = io.read()
-- now convert to hexadecimal. If it isn't a valid hexadecimal char, clear it and start over.
-- QUARRY
i = 1
local rbx = 0
while i <= #m200000 do
al = m200000:byte(i)
if al < string.byte("0") then
-- fail
print("FAILED TO PARSE HEX. INVALID CHARS")
return hexread()
else
if al > string.byte("9") then
-- NET 1
if al < string.byte("A",1) then
print("FAILED TO READ HEX")
return hexread()
else
if al > string.byte("F") then
-- NET TWO WOULD GO HERE, BUT IS BEYOND SCOPE
print("FAILED TO READ HEX")
return hexread()
else
-- subtract 'A' from al
-- and then add ten
al = al - string.byte("A")
al = al + 10
end
end
else
-- subtract '0'
al = al - string.byte("0")
end
end
rbx = rbx << 4
rbx = rbx | al
i = i+1
end
return rbx
end
My function doesn't get past the jl directive at the cmp al, '0'.
For my assembly, I should mention that READLN and WRITELN are both tested functions that work. READLN gets keys from the user, and stores the resulting string at address rbx placing a NULL at the end, when the user presses enter. (the LF is not saved in memory) This has been confirmed working.
WRITELN also works, it takes a rsi at a specified address, and prints the string to video memory.
Finally, I should mention that characters 80h to 85h are special characters that I also want to be able to use with hexadecimal.
So here is my question, Since my Lua code works, and my ASM does not, I am not accuritely representing asm in lua.
What are some tips to better prototype asm?
I see several problems with my current approach:
- Using m200000 to represent that slot in memory is pretty dumb. I have tested and the asm function is fetching the right characters from memory, so it is not a memleak causing it. EDIT: It totally was, but in a different way. However this strengthens the question. That said, are there better strategies for prototyping with memory slots. (also, I probably should have READLN place the value on the stack.)
- Since my lua "registers" are actually ordinary variables, I can see register related problems arising,
- lua uses a more structured approach to conditional execution that x86, so label related problems could go undetected. In some ways I think there is an advantage to it (like being able to express your idea in a basic fashion, and then adjust for assembly) but obviously without a GOTO that could be problematic.
TL;DR:
My ASM was okay, but there was a memory problem, that the prototype code didn't detect.
What are some tips for prototyping asm in a higher level language?
When, if ever should this be done?
And finally, how useful is prototyping in debugging?