这个法西斯x64 (Linux)代码看起来非常粗糙和重复,但它完成了工作。我怎样才能以一种更惯用的方式来完成这个任务呢?
format ELF64 executable 3
segment readable executable
entry $
prompt_user:
mov edx,prompt_len
lea rsi,[prompt] ;<------ String
mov edi,1 ; STDOUT
mov eax,1 ; sys_write
syscall
get_user_input:
mov rax, 0 ; sys_read
mov rdi, 0 ; STDIN
lea rsi, [bit_string] ; <----- defined memory location
mov rdx, 2 ; <---- # of chars to read
syscall
;DEBUG CODE:
;lea rax, [bit_string]
;mov [rax], byte 'A'
;mov [rax+1], byte 'B'
lea rax, [bit_string]
cmp [rax], byte '0'
je load_0
cmp [rax], byte '1'
je load_1
cmp [rax], byte '2'
je load_2
cmp [rax], byte '3'
je load_3
cmp [rax], byte '4'
je load_4
cmp [rax], byte '5'
je load_5
cmp [rax], byte '6'
je load_6
cmp [rax], byte '7'
je load_7
cmp [rax], byte '8'
je load_8
cmp [rax], byte '9'
je load_9
cmp [rax], byte 'A'
je load_A
cmp [rax], byte 'B'
je load_B
cmp [rax], byte 'C'
je load_C
cmp [rax], byte 'D'
je load_D
cmp [rax], byte 'E'
je load_E
cmp [rax], byte 'F'
je load_F
load_0:
lea rsi, [n0]
jmp print_nibble
load_1:
lea rsi, [n1]
jmp print_nibble
load_2:
lea rsi, [n2]
jmp print_nibble
load_3:
lea rsi, [n3]
jmp print_nibble
load_4:
lea rsi, [n4]
jmp print_nibble
load_5:
lea rsi, [n5]
jmp print_nibble
load_6:
lea rsi, [n6]
jmp print_nibble
load_7:
lea rsi, [n7]
jmp print_nibble
load_8:
lea rsi, [n8]
jmp print_nibble
load_9:
lea rsi, [n9]
jmp print_nibble
load_A:
lea rsi, [nA]
jmp print_nibble
load_B:
lea rsi, [nB]
jmp print_nibble
load_C:
lea rsi, [nC]
jmp print_nibble
load_D:
lea rsi, [nD]
jmp print_nibble
load_E:
lea rsi, [nE]
jmp print_nibble
load_F:
lea rsi, [nF]
jmp print_nibble
nibble_two:
lea rax, [bit_string]
cmp [rax+1], byte '0'
je load_0
cmp [rax+1], byte '1'
je load_1
cmp [rax+1], byte '2'
je load_2
cmp [rax+1], byte '3'
je load_3
cmp [rax+1], byte '4'
je load_4
cmp [rax+1], byte '5'
je load_5
cmp [rax+1], byte '6'
je load_6
cmp [rax+1], byte '7'
je load_7
cmp [rax+1], byte '8'
je load_8
cmp [rax+1], byte '9'
je load_9
cmp [rax+1], byte 'A'
je load_A
cmp [rax+1], byte 'B'
je load_B
cmp [rax+1], byte 'C'
je load_C
cmp [rax+1], byte 'D'
je load_D
cmp [rax+1], byte 'E'
je load_E
cmp [rax+1], byte 'F'
je load_F
print_intro:
mov edx,intro_len
lea rsi,[intro]
mov edi,1 ; STDOUT
mov eax,1 ; sys_write
syscall
ret
print_nibble:
cmp [position], 0 ; If were on first iter, then print intro
jne skip_intro
push rsi
call print_intro
pop rsi
skip_intro:
mov rax, 1
cmp al, [position]
jl go_out
mov edx, 4
mov edi,1 ; STDOUT
mov eax,1 ; sys_write
syscall
add [position], 1
jmp nibble_two
go_out:
mov edx,1
lea rsi,[nl]
mov edi,1 ; STDOUT
mov eax,1 ; sys_write
syscall
xor edi,edi ; exit code 0
mov eax,60 ; sys_exit
syscall
segment readable writeable
prompt db 'Enter a byte in the format: F6', 0xA
prompt_len = $ - prompt
nl db 0xA
intro db 'In binary: ', 0
intro_len = $ - intro
bit_string rb 2
position db 0
n0 db '0000', 0
n1 db '0001', 0
n2 db '0010', 0
n3 db '0011', 0
n4 db '0100', 0
n5 db '0101', 0
n6 db '0110', 0
n7 db '0111', 0
n8 db '1000', 0
n9 db '1001', 0
nA db '1010', 0
nB db '1011', 0
nC db '1100', 0
nD db '1101', 0
nE db '1110', 0
nF db '1111', 0发布于 2019-11-30 11:00:25
在高级语言中,我会把它写成:
def put_nibble(buf: array[byte], n: int):
buf[0] = '0' + ((n shr 3) bitand 1)
buf[1] = '0' + ((n shr 2) bitand 1)
buf[2] = '0' + ((n shr 1) bitand 1)
buf[3] = '0' + ((n shr 0) bitand 1)
def char_to_nibble(ch: byte) -> int:
if '0' <= ch <= '9': return ch
ch = ch bitor 0x20 # convert to lowercase
if 'a' <= ch <= 'z': return ch - 'a' + 10
error
def byte_to_binary(b: str):
buf = byte[8] # reserve memory on the stack
hi = char_to_nibble(b[0])
put_nibble(buf, hi)
lo = char_to_nibble(b[1])
put_nibble(but + 4, lo)
sys_write(1, buf, 8)这样,您就可以避免单独比较每个可能的数字。
上面的代码还减少了对堆栈上内存的访问,因为它不需要任何外部字符串来处理位模式。
当然,put_nibble代码看起来有点重复,但是您可以将所有'0' + …合并到一个单独的添加中:
add dword [buf], 0x30303030 ; 0x30 == '0'您还可以计算寄存器中的整个缓冲区,然后在一条指令中将其写入内存:
; input: al = the nibble to print
; output: ebx = 4 bytes ASCII buffer containing the 4 binary digits
xor ebx, ebx
rcr al, 1
adc ebx, '0'
rol ebx, 8
rcr al, 1
adc ebx, '0'
rol ebx, 8
rcr al, 1
adc ebx, '0'
rol ebx, 8
rcr al, 1
adc ebx, '0'
rol ebx, 8
mov [buf], ebx一旦您将上述高级代码翻译成汇编程序,您可能希望对代码进行一些优化。或者只需使用编译器为您完成繁重的工作。用C语言或Go语言编写代码,将其组装成机器代码,然后查看结果。一些用于搜索的关键字:
顺便说一句,您不应该将提示符和位模式的字符串文本放在writeable段中,因为它们不打算被程序的任何部分覆盖。
https://codereview.stackexchange.com/questions/233183
复制相似问题