1

I made this simple assembly program:

.text

.globl _start:

_start:
    movl $1, %rax
    movl $0, %rbx
    int 0x80

The original program I took this from used %eax and %ebx instead of %rax and %rbx since it was 32 bit. And since my OS is a 64 bit Linux (Not running on as a virtual machine), i just replaced the registers. But here's what happens when I compile:

ExitShellcode.s: Assembler messages:
ExitShellcode.s:6: Error: incorrect register `%rax' used with `l' suffix
ExitShellcode.s:7: Error: incorrect register `%rbx' used with `l' suffix
ExitShellcode.s:8: Error: operand size mismatch for `int'

what do I need to do??

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Dark Eagle
  • 107
  • 3
  • 10
  • 1
    Depends on what $1 is referring to. Try movq – Jens Munk Jun 17 '16 at 20:34
  • as you are going to compile for 32bit target you need to install and use 32bit toolchain. – Serge Jun 17 '16 at 20:35
  • `movl` in `movl $1, %rax` means move the long 32-bit value of the source operand.to the destination. Because the destination is a 64-bit register (RAX) and we are trying to move 32-bits to it, NASM complains. You can either change `movl` to `movq` or NASM can also infer the size if the source or target size is known (The size of RAX is known to be 64-bits).`int 0x80` should be `int $0x80` 0x80 is a constant (immediate) so you need `$`. Otherwise you are trying to get the assembler to get what is at memory location `0x80` and use its value for the interrupt (which isn't supported by the CPU) – Michael Petch Jun 17 '16 at 20:46
  • 1
    Usually if you are trying to move an unsigned integer that can fit in 32-bit, you can `mov` it to the 32-bit register and have the CPU automatically zero extend it to the entire width of the 64-bit register. `movl $1, %eax` would move 1 into eax, and theCPU will automatically zero extend it to all of RAX. So RAX would have 0x0000000000000001. This zero extending only applies in 64-bit code where the destination is a 32-bit register. – Michael Petch Jun 17 '16 at 20:51
  • Effectively you could have written the lines as `mov $1, %eax` and `movl $0, %ebx` . One benefit is that this saves one extra byte on each instruction encoding compared with `mov $1, %rax` `movl $0, %rbx` XOR can also be used to zero a register (which is often the preferred idiom). For instance `xor %eax, %eax` will zero out all of _RAX_. – Michael Petch Jun 17 '16 at 21:02
  • When I said NASM above, I meant GNU assembler. My apologies for the typo. – Michael Petch Jun 17 '16 at 21:04
  • @MichaelPetch You are correct. Thanks for the awesome and clear response. – Dark Eagle Jun 17 '16 at 21:16
  • @JensMunk That helped. Thanks – Dark Eagle Jun 17 '16 at 21:16
  • Are you actually trying to assemble 32bit examples on 64bit Linux, like your question title says? If so, see [this link](http://stackoverflow.com/questions/36861903/assembling-32-bit-binaries-on-a-64-bit-system-gnu-toolchain/36901649#36901649) from the FAQ section of [the x86 tag wiki](http://stackoverflow.com/tags/x86/info). If you're instead trying to port your examples to 64bit, keep in mind that using 32bit `int 0x80` system calls in 64bit code will cause problems as soon as you try to pass a pointer larger than 32 bits. Use `syscall` (with different syscall numbers). – Peter Cordes Jun 18 '16 at 00:01
  • Since you are moving from 32-bit code to 64-bit code you might want to consider replacing `int $0x80` with `syscall`. You can use `int 0x80` but there are cases where 64-bit addresses can't be passed properly. generally it is a good idea to give up on `int $0x80` in 64-bit code and favor the `syscall` convention. It is similar in nature to `int 0x80` but the parameters are passed in different registers and syscall numbers are different. A good place to start is Ryan Chapman's blog http://blog.rchapman.org/post/36801038863/linux-system-call-table-for-x86-64 – Michael Petch Jun 18 '16 at 02:21

0 Answers0