x86 32 位汇编中的 BrainF*ck 解释器
BrainF*ck interpreter in x86 32-bit Assembly
我开始用 32 位 x86 汇编为我的 OS 编写一个 BrainF*ck 解释器。我已经用 C 编写了一个可以正常工作的程序,并尝试在汇编中实现它,但是用汇编编写的那个不打印任何输出。
我对汇编还是个新手,所以我想我只是犯了一些初学者的错误。我唯一能想到的就是我搞砸了某处的寻址。
如果有人能指出我做错了什么,我会很高兴。
我用相同的输入测试了 C 和汇编程序:
-[--->+<]>---.+[----->+++<]>.[--->+<]>+.[--->++<]>-.++++.
它应该打印 RexOS
我创建了我的 C 代码的 pastebin 如果这有助于理解我想要完成的事情:
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) 中保存额外的寄存器,然后在尾声中恢复寄存器。还需要保存和恢复打印和扫描部分的寄存器。
我的最终工作代码如下所示:
.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
我开始用 32 位 x86 汇编为我的 OS 编写一个 BrainF*ck 解释器。我已经用 C 编写了一个可以正常工作的程序,并尝试在汇编中实现它,但是用汇编编写的那个不打印任何输出。
我对汇编还是个新手,所以我想我只是犯了一些初学者的错误。我唯一能想到的就是我搞砸了某处的寻址。 如果有人能指出我做错了什么,我会很高兴。
我用相同的输入测试了 C 和汇编程序:
-[--->+<]>---.+[----->+++<]>.[--->+<]>+.[--->++<]>-.++++.
它应该打印 RexOS
我创建了我的 C 代码的 pastebin 如果这有助于理解我想要完成的事情: 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) 中保存额外的寄存器,然后在尾声中恢复寄存器。还需要保存和恢复打印和扫描部分的寄存器。
我的最终工作代码如下所示:
.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