如何将指定C程序转换为内联汇编?
Hey there! Let's convert your C program to inline assembly—assuming you're targeting x86-64 Linux with GCC (since inline assembly syntax varies a lot by compiler/architecture). I also fixed a small bug in the original code where the final printf was missing the loop counter argument and a newline.
Converted Inline Assembly Version
#include <stdio.h> #include <string.h> int main() { int counter = 0; int input = 0; char name[20]; // Prompt user for integer input asm volatile ( "mov $prompt_int, %%rdi\n" // Load format string address into first arg register "xor %%rax, %%rax\n" // No floating-point args, so RAX = 0 "call printf\n" // Call printf : : "m"(prompt_int) // Input: reference to prompt string : "rdi", "rax", "rcx", "r11" // List registers modified by this block ); // Read integer input from user asm volatile ( "mov $fmt_int, %%rdi\n" // Load scanf format string "lea %0, %%rsi\n" // Load address of input variable into second arg "xor %%rax, %%rax\n" "call scanf\n" // Call scanf : "=r"(input) // Output: store result in input variable : "m"(fmt_int) : "rdi", "rsi", "rax", "rcx", "r11" ); // Print the entered integer asm volatile ( "mov $fmt_print_int, %%rdi\n" "mov %0, %%rsi\n" // Pass input as second arg "xor %%rax, %%rax\n" "call printf\n" : : "r"(input), "m"(fmt_print_int) : "rdi", "rsi", "rax", "rcx", "r11" ); // Check for invalid input (<=0) and print error asm volatile ( "cmp $0, %0\n" "jg skip_error\n" // Jump past error if input >0 "mov $err_msg, %%rdi\n" "xor %%rax, %%rax\n" "call printf\n" "skip_error:\n" : : "r"(input), "m"(err_msg) : "rdi", "rax", "rcx", "r11", "cc" // Clobber condition codes (cc) ); // Prompt for name only if input is valid asm volatile ( "cmp $0, %0\n" "jle skip_name_prompt\n" // Skip if input <=0 "mov $prompt_name, %%rdi\n" "xor %%rax, %%rax\n" "call printf\n" "skip_name_prompt:\n" : : "r"(input), "m"(prompt_name) : "rdi", "rax", "rcx", "r11", "cc" ); // Read name if input is valid asm volatile ( "cmp $0, %0\n" "jle skip_name_read\n" "mov $fmt_str, %%rdi\n" "lea %1, %%rsi\n" // Load address of name buffer "xor %%rax, %%rax\n" "call scanf\n" "skip_name_read:\n" : : "r"(input), "m"(name), "m"(fmt_str) : "rdi", "rsi", "rax", "rcx", "r11", "cc" ); // Loop from 1 to input: print name and counter int i; asm volatile ( "mov $1, %%r10\n" // Initialize loop counter to 1 "loop_start:\n" "cmp %0, %%r10\n" "jg loop_end\n" // Exit loop if counter > input // Print user's name "mov $fmt_print_name, %%rdi\n" "lea %1, %%rsi\n" "xor %%rax, %%rax\n" "call printf\n" // Print current counter value "mov $fmt_print_count, %%rdi\n" "mov %%r10, %%rsi\n" "xor %%rax, %%rax\n" "call printf\n" "inc %%r10\n" // Increment counter "jmp loop_start\n" "loop_end:\n" : "=r"(i) // Output: final counter value (unused, but complete) : "m"(name), "r"(input), "m"(fmt_print_name), "m"(fmt_print_count) : "rdi", "rsi", "rax", "rcx", "r11", "r10", "cc" ); return 0; } // String literals referenced in assembly const char prompt_int[] = "Please input an integer value 1 - 99: "; const char fmt_int[] = "%d"; const char fmt_print_int[] = "You entered: %d\n"; const char err_msg[] = "Error, invalid input \n"; const char prompt_name[] = "Please input name \n"; const char fmt_str[] = "%s"; const char fmt_print_name[] = "Your name is %s\n"; const char fmt_print_count[] = "%d...\n"; // Fixed missing newline and argument
Key Details to Note:
- Uses the x86-64 System V calling convention (standard for Linux/macOS/BSD), where function arguments are passed in
RDI,RSI,RDX, etc. asm volatileprevents the compiler from optimizing away our assembly blocks (critical for I/O operations).- We explicitly list clobbered registers so the compiler knows which registers our assembly modifies—this avoids conflicts with compiler-generated code.
- Fixed the original C bug where
printf("%d...");was missing the loop counter argument and a newline character. - String literals are defined as global constants so the assembly can reference their memory addresses directly.
内容的提问来源于stack exchange,提问作者John H
相关产品推荐
相关产品推荐

