| ... | @@ -80,28 +80,32 @@ pub fn syscall6( | ... | @@ -80,28 +80,32 @@ pub fn syscall6( |
| 80 | arg5: usize, | 80 | arg5: usize, |
| 81 | arg6: usize, | 81 | arg6: usize, |
| 82 | ) usize { | 82 | ) usize { |
| 83 | // arg5/arg6 are passed via memory as we're out of registers if ebp is used as frame pointer, or | 83 | // arg6 can't be passed to asm in a register because ebp might be reserved as the frame pointer |
| 84 | // if we're compiling with PIC. We push arg5/arg6 on the stack before changing ebp/esp as the | 84 | // and there are no more GPRs available; so we'll need a memory operand for it. Adding that |
| 85 | // compiler may reference arg5/arg6 as an offset relative to ebp/esp. | 85 | // memory operand means that on PIC we might need a reference to the GOT, which in turn needs |
| | 86 | // *its* own GPR, so we need to pass another arg in memory too! This is surprisingly hard to get |
| | 87 | // right, because we can't touch esp or ebp until we're done with the memory input (as that |
| | 88 | // input could be relative to esp or ebp). |
| | 89 | const args56: [2]usize = .{ arg5, arg6 }; |
| 86 | return asm volatile ( | 90 | return asm volatile ( |
| 87 | \\ push %[arg5] | 91 | \\ push %[args56] |
| 88 | \\ push %[arg6] | | |
| 89 | \\ push %%edi | | |
| 90 | \\ push %%ebp | 92 | \\ push %%ebp |
| 91 | \\ mov 12(%%esp), %%edi | 93 | \\ mov 4(%%esp), %%ebp |
| 92 | \\ mov 8(%%esp), %%ebp | 94 | \\ mov %%edi, 4(%%esp) |
| | 95 | \\ // The saved %edi and %ebp are on the stack, and %ebp points to `args56`. |
| | 96 | \\ // Prepare the last two args, syscall, then pop the saved %ebp and %edi. |
| | 97 | \\ mov (%%ebp), %%edi |
| | 98 | \\ mov 4(%%ebp), %%ebp |
| 93 | \\ int $0x80 | 99 | \\ int $0x80 |
| 94 | \\ pop %%ebp | 100 | \\ pop %%ebp |
| 95 | \\ pop %%edi | 101 | \\ pop %%edi |
| 96 | \\ add $8, %%esp | | |
| 97 | : [ret] "={eax}" (-> usize), | 102 | : [ret] "={eax}" (-> usize), |
| 98 | : [number] "{eax}" (@intFromEnum(number)), | 103 | : [number] "{eax}" (@intFromEnum(number)), |
| 99 | [arg1] "{ebx}" (arg1), | 104 | [arg1] "{ebx}" (arg1), |
| 100 | [arg2] "{ecx}" (arg2), | 105 | [arg2] "{ecx}" (arg2), |
| 101 | [arg3] "{edx}" (arg3), | 106 | [arg3] "{edx}" (arg3), |
| 102 | [arg4] "{esi}" (arg4), | 107 | [arg4] "{esi}" (arg4), |
| 103 | [arg5] "rm" (arg5), | 108 | [args56] "rm" (&args56), |
| 104 | [arg6] "rm" (arg6), | | |
| 105 | : .{ .memory = true }); | 109 | : .{ .memory = true }); |
| 106 | } | 110 | } |
| 107 | | 111 | |