我开始在32位x86程序集中为我的操作系统编写BrainF*ck解释器。我已经用C编写了一个可以工作的程序,并试图在汇编中实现它,但用汇编编写的程序不打印任何输出。
我还是组装新手,所以我想我只是犯了一些初学者的错误。我唯一能想到的就是我把地址搞砸了。如果有人能指出我做错了什么,我会非常高兴。
我用相同的输入测试了C和汇编程序:
-[--->+<]>---.+[----->+++<]>.[--->+<]>+.[--->++<]>-.++++.
应打印RexOS
我创建了一个C代码的pastebin,如果这有助于理解我试图实现的目标:粘贴式
我的汇编代码如下:
.intel_syntax noprefix
.section .data
TAPE:
.zero 30000
.section .text
.global interpret
interpret:
push ebp // prologue
mov ebp, esp
mov edx, [ebp+8] // getting the input string
mov edi, offset TAPE // a pointer to the tape
xor ecx, ecx // stores current char
// inner loop counter
loop:
mov cl, byte ptr [edx] // getting the current char
inc edx // increase the index to the next char
cmp cl, 0 // if we reached the end of the string
je exit // return the length
cmp cl, '>'
je pinc // increment the pointer
cmp cl, '<'
je pdec // decrement the pointer
cmp cl, '+'
je vinc // increment value at index
cmp cl, '-'
je vdec // decrement value at index
cmp cl, '.'
je prnt // print the value at index
cmp cl, ','
je read // read character from stdin
cmp cl, ']'
je bend // end of bracket
jmp loop
pinc:
inc edi
jmp loop
pdec:
dec edi
jmp loop
vinc:
inc byte ptr [edi]
jmp loop
vdec:
dec byte ptr [edi]
jmp loop
prnt:
push edx
push dword ptr [edi]
call putchar
add esp, 4
pop edx
jmp loop
read:
call getchar
mov byte ptr [edi], al
jmp loop
bend:
cmp byte ptr [edi], 0
je loop
mov ch, 1
ilst:
cmp ch, 0
jle loop
dec edx // jump to the previous index
mov cl, byte ptr [edx] // getting the current char
cmp cl, '['
je dclp // decrease internal loop counter
cmp cl, ']'
je inlp // increase internal loop counter
jmp ilst
inlp:
inc ch
jmp ilst
dclp:
dec ch
jmp ilst
exit:
mov esp, ebp // epilogue
pop ebp
ret
我终于解决了这个问题。我所需要做的就是将指针增量移动到循环的末尾,并在序言(ebx(中保存额外的寄存器,然后在后记中恢复寄存器。还需要保存和恢复prnt和扫描部分中的寄存器。
我的最终工作代码如下:
.intel_syntax noprefix
.section .data
TAPE:
.zero 30000
.section .text
.global interpret
interpret:
push ebp // prologue
mov ebp, esp
push ebx
xor eax, eax // loop counter
mov ebx, offset TAPE // a pointer to the tape
mov edx, [ebp+8] // getting the input string
clrt: // clear TAPE
cmp eax, 30000
je loop
mov byte ptr [ebx+eax], 0
inc eax
jmp clrt
loop:
mov cl, byte ptr [edx] // getting the current char
cmp cl, 0 // if we reached the end of the string
je exit // return the length
cmp cl, '>'
je pinc // increment the pointer
cmp cl, '<'
je pdec // decrement the pointer
cmp cl, '+'
je vinc // increment value at index
cmp cl, '-'
je vdec // decrement value at index
cmp cl, '.'
je prnt // print the value at index
cmp cl, ','
je read // read character from stdin
cmp cl, ']'
je bend // end of bracket
ptlp: // postloop
inc edx // increment the input pointer
jmp loop // continue the loop
pinc:
inc ebx
jmp ptlp
pdec:
dec ebx
jmp ptlp
vinc:
inc byte ptr [ebx]
jmp ptlp
vdec:
dec byte ptr [ebx]
jmp ptlp
prnt:
push edx
push dword ptr [ebx]
call putchar
add esp, 4
pop edx
jmp ptlp
read:
push edx
call getchar
mov byte ptr [ebx], al
pop edx
jmp ptlp
bend:
cmp byte ptr [ebx], 0
je ptlp
mov ch, 1
ilst:
cmp ch, 0
jle ptlp
dec edx // jump to the previous index
mov cl, byte ptr [edx] // getting the current char
cmp cl, '['
je dclp // decrease internal loop counter
cmp cl, ']'
je inlp // increase internal loop counter
jmp ilst
inlp:
inc ch
jmp ilst
dclp:
dec ch
jmp ilst
exit:
pop ebx // epilogue
mov esp, ebp
pop ebp
ret