1

Hello everyone, I am implementing the bind system call in Assembler x64 with NASM for developing a TCP socket. I have the following code and it works:

mov rdi, [socket]           
push dword 0x6B02A8C0       
push word  0x560f           
push word  2                
mov rsi, rsp                
mov rdx, dword 32
mov rax, 49                 
syscall

The structure to follow is as follows:

rdi --> int fd
rsi --> struct sockaddr __user * umyaddr
rdx --> int addrlen
rax --> syscall

I understand quite well about implementing the system call, my problem is with system calls that need a structure, I know that the structure is inserted on the stack and then the pointer is passed to the register, but I don't understand why I need to put "push dword, 0x00000000" and not just "push, 0x00000000", I read that it was exactly the same, but because removing the "dword" and "word" and it doesn't work, the program runs, and it doesn't throw an error but when I try to connect to the socket as client is as if there were no open socket.

Anyway, what is the difference between putting "dword" and not putting it? Or am I implementing the structure wrong, is it fine or am I missing a parameter? I want to know well what it does to understand it, it is good that it works but if I do not understand it it does not work for me.

From already thank you very much!!

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • 2
    Unfortunately, NASM allows `push dword 123` even though it *doesn't* set the operand-size (it's still qword), unlike `push word 123` which does. [Why does the push DWORD instruction equalize on 8 bytes?](https://stackoverflow.com/q/65269161). (`push strict dword 123` makes sense to set the immediate width.) – Peter Cordes Apr 12 '21 at 02:39
  • 1
    Fortunately for your use-case, pushing an extra 4 bytes of zeros above your `0x6B02A8C0` doesn't break anything. Although you could do `mov rax, 0x6B02A8C0_560f_0002` / `push rax`. (`_` is silently ignored in hex numbers so you can use it as a separator, like `'` in C++11) – Peter Cordes Apr 12 '21 at 02:44
  • @PeterCordes adding 4 bytes of 0 did not work, in fact it is something that I had already tried, I like the idea of putting it in the registry and then inserting it on the stack, but do you have any idea which one would have better performance? I mean use "push dword, push word" or "mov rax, ..." – Franco Milich Apr 12 '21 at 22:59
  • Your current code *already* pushes 4 extra bytes of zeros *above* your data, as part of `push 0x6B02A8C0` (push qword with a sign-extended 32-bit immediate). Look at stack memory with a debugger. – Peter Cordes Apr 13 '21 at 00:12
  • For performance, `mov rax, imm64` / `push rax` is best: smaller total code size, fewer uops, and only one wide store instead of 3 stores. Fetching a 64-bit immediate from the uop cache can take an extra cycle in that part of the front-end according to [Agner Fog's](https://agner.org/optimize/) microarch PDF (Sandybridge section), but still overall worth it. Don't write `push dword` in your source code, it's misleading since you literally can't make `push` only move RSP by 4 in 64-bit mode. It's actually a qword push. – Peter Cordes Apr 13 '21 at 00:16
  • The other option would be `push 0x560f_0002` / `mov dword [rsp+4], 0x6B02A8C0` to push a qword immediate in two halves, storing the upper half manually. But that's probably still slightly worse than mov rax,imm64 / push rax. – Peter Cordes Apr 13 '21 at 00:19
  • `;push 0x6B02A8C0` `;push 0x560f ` `;push 2` `; 00007ffe:3650f6c8|0000000000000002|........|` `; 00007ffe:3650f6d0|000000000000560f|.V......|` `; 00007ffe:3650f6d8|000000006b02a8c0|...k....|` `; push dword 0x6B02A8C0` `; push word 0x560f` `; push word 2` `; 00007ffd:37474724|6b02a8c0560f0002|...V...k|` – Franco Milich Apr 13 '21 at 00:21
  • @PeterCordes I don't know how to put it to make it look better, but anyway those are the results of the two types of inserts in the stack – Franco Milich Apr 13 '21 at 00:25
  • Yeah, I know how NASM and x86-64 work for this, the key is for *you* to understand it. Of course `push 0x560f` pushes a whole qword, that's the key point of the answer on the linked duplicate. As I said, `push word` makes it a different instruction, `push dword` doesn't. – Peter Cordes Apr 13 '21 at 00:26
  • For your 2nd version you only dumped 8 bytes of memory, ignoring the 4 bytes of zeros above the `00007ffd:37474724` address. Notice that your 2nd sequence moves RSP by a total of 12, 8 + 2 + 2. It's not emulating a single qword push, `push dword 0x6B02A8C0` already *is* a qword push (with a dword immediate), so like I said it's very misleading to write it that way in your source. – Peter Cordes Apr 13 '21 at 00:28
  • That is a bit confusing, precisely for that reason I asked this question, since you tell me that it is better to add it to the registry and then insert it into the stack. I will choose that option, thank you very much for your time @PeterCordes – Franco Milich Apr 13 '21 at 00:34
  • Yes, it's confusing, that's why I explained that fact in my very first comment and linked it as a duplicate of an answer with the full details. Also, [nasm 64 bit push qword?](https://stackoverflow.com/q/12544957) has an example in the question, and of what you should do in the answer, so I added it as another duplicate. – Peter Cordes Apr 13 '21 at 00:46

0 Answers0