32位汇编代码转64位方案及字符串长度多计数问题咨询
Hey there! Let's tackle your two assembly problems step by step.
x86-64 Linux uses different system calling conventions than 32-bit: we use syscall instead of int 80h, 64-bit registers, and updated system call numbers. Here's how to adjust your code:
- Replace 32-bit registers with 64-bit equivalents: Swap
eax→rax,ebx→rbx,ecx→rcx,edx→rdx(64-bit registers handle 64-bit addresses properly). - Update system call numbers:
sys_writeis now1(was4in 32-bit)sys_readis now0(was3in 32-bit)sys_exitis now60(was1in 32-bit)
- Use
syscallinstead ofint 80h: This is the standard way to invoke kernel functions in 64-bit mode. - Ensure stack alignment: 64-bit Linux requires the stack to be 16-byte aligned before
syscall. Adding a simple stack setup at the start fixes this.
Here's the revised 64-bit code:
section .text global _start _start: ; Align stack to 16 bytes push rbp mov rbp, rsp ; Show prompt message mov rdx, 19 ; Number of bytes to write (including newline) mov rcx, txt_prompt ; Address of prompt string mov rbx, 1 ; STDOUT file descriptor mov rax, 1 ; SYS_WRITE syscall number syscall ; Read user input mov rax, 0 ; SYS_READ syscall number mov rbx, 0 ; STDIN file descriptor mov rcx, user_input ; Destination buffer mov rdx, 100 ; Max bytes to read syscall ; Optional: Replace newline with null terminator (fixes length issue too) cmp byte [user_input + rax - 1], 0xA jne skip_replace mov byte [user_input + rax - 1], 0 skip_replace: ; Calculate string length mov rbx, user_input ; Base address of input mov rax, rbx ; Current address pointer strlen_nextchar: cmp byte [rax], 0 ; Check for null terminator jz strlen_finished ; Exit loop if found inc rax ; Move to next byte jmp strlen_nextchar strlen_finished: sub rax, rbx ; Compute length (current - base) ; Update output string with length (since length <10, we can just add to the digit) add byte [txt_output + 33], al ; Print result mov rdx, 34 ; Length of output string (including newline) mov rcx, txt_output ; Address of output string mov rbx, 1 ; STDOUT mov rax, 1 ; SYS_WRITE syscall ; Exit program mov rbx, 0 ; Exit code 0 mov rax, 60 ; SYS_EXIT syscall number syscall section .data txt_prompt: db 'Enter your message:', 0Ah txt_output: db 'The string length is calculated: 0', 0Ah section .bss user_input: resb 100
The problem isn't related to \x10 or \x13—it's about how the read syscall works. When you type input and press enter, Linux adds a newline character (\n, \x0A) to the input buffer. Your original code was looking for a null terminator (0), but the input buffer doesn't have one by default. So your strlen loop counted the newline character (and potentially extra bytes until it hit a random null in memory) as part of the length.
The fix we added above addresses this: right after reading input, we check if the last character is a newline, and replace it with a null terminator. This way, your strlen loop stops at the end of the actual input (excluding the newline), giving you the correct length.
If you want to confirm, try running the original code and entering "test"—it would return 5 instead of 4, because it counts "test\n". The fix makes it return 4 as expected.
内容的提问来源于stack exchange,提问作者ar2015

