-2

Write an assembly procedure called increment that is callable from C. The procedure should take a pointer to 32-bit integer as a parameter, and should increment the integer to which the parameter points. The C prototype for the function is as follows:

void increment (int *p);

Provide only the assembly code from the procedure label to the ret instruction.

So, the question has to be done in Assembly NASM x86-64 (in this case, E registers since it's asking for 32-bit). Assuming everything else is already declared and defined such as extern, global, section .data, it's generally a short segment of logical instructions of 3-12 lines of code in _start: that I have to code; this is the code:

increment:
        push    rbp
        mov     rbp, rsp
        mov     QWORD PTR [rbp-8], rdi
        mov     rax, QWORD PTR [rbp-8]
        mov     eax, DWORD PTR [rax]
        lea     edx, [rax+1]
        mov     rax, QWORD PTR [rbp-8]
        mov     DWORD PTR [rax], edx
        nop
        pop     rbp
        ret

I know that PTR is't apart of NASM keyword, but my confusion comes from whether to remove PTR or keep it, and whether I should be using both E registers and R registers. I believe mine is somewhat correct, but if someone could double check my code to see if it's logic makes sense from the question standpoint, that'd be wonderful.

The code below is a C file I have to call from using such things like scanf or printf, but since I'm not using those for this code I wonder if I'm doing it wrong since those are important to C. From what I understand there are other ways of going about with this question; I'm not sure how I would go about in translating this C code into NASM through alternative means:

void increment  (int *p) {
    *p = *p + 1;
} 
Atlas
  • 11
  • 3
  • @user3840170 Yes, and No. The parameter part is wonderful, thank you for linking me that. I just need a pair of eyes to double-check if my code makes sense and nothing's wrong, and if it is, how I can go about improving it – Atlas Dec 15 '21 at 20:55
  • @old_timer would the code I have above somewhat make sense instruction logic-wise to the question on hand? – Atlas Dec 15 '21 at 20:58
  • 2
    Don't repost the same question. In any case, fuz has given you the code on your previous question. Your code looks like something generated by a non-optimizing compiler. It is doing tons of unnecessary stack operations. – Jester Dec 15 '21 at 21:00
  • 2
    Hint, this can be done with exactly two instructions, and one of them is `ret`. – Nate Eldredge Dec 15 '21 at 21:03
  • By the way, if you're assigned to write something in assembler, and you hand in code that is obviously compiler output, then your instructor is likely to give you zero points and maybe start academic dishonesty proceedings. (And what you have there is pretty darn obvious, to anyone familiar with such things.) – Nate Eldredge Dec 15 '21 at 21:15
  • @NateEldredge Oh no, it's not assigned, however, it is from a practice example in the textbook that I'm studying for, and this question is the one that I'm really stuck in for some time. Sorry if I offended you (?) – Atlas Dec 15 '21 at 21:38
  • @Jester Yep, I saw his response. I didn't get a notification so I didn't notice he responded, thanks for the reminder. I won't repost the same question a second time, sorry. Just that I'm really stuck and can't seem to find anyone in the class that knows assembly (and my teacher's on vacation) besides this site to help me with assembly questions. Feel like I've reached an end of the tunnel – Atlas Dec 15 '21 at 21:50
  • If it's for your own studying then there's nothing wrong with looking at compiler output. Just turn on optimizations if you want anything halfway sensible. https://godbolt.org/z/9oMsxY834 does the "obvious" thing; `inc dword ptr [rdi]` would be pretty similar. – Nate Eldredge Dec 15 '21 at 22:50
  • The general principle in 64-bit code is always use 64-bit registers for pointers / addresses. The function parameter here in rdi is a pointer, so you use it. Distinguish between the *address size* and the *operand size* of the instruction. `add dword ptr [rdi], 1` has an address size of 64 bits (because of the use of `rdi`) and an operand size of 32 bits (because of `dword`). So it takes a 64-bit address and accesses a 32-bit object at that address, which is just what you want. – Nate Eldredge Dec 15 '21 at 22:51
  • Hey @NateEldredge I'm sorry again for the late response! Thanks for the response. I don't think PTR is necessary since we are using nasm keywords, no? And I suppose `inc dword [rdi]; ret` would work as well, since by logic adding 1 is the same as incrementing. – Atlas Dec 16 '21 at 03:00
  • The other really important part of my [How to remove "noise" from GCC/clang assembly output?](https://stackoverflow.com/q/38552116) was to enable optimization. That would have got you a 1 instruction (plus ret) version to start with that was nice and easy to read, not this confusing mess that `gcc -O0` produces. – Peter Cordes Dec 16 '21 at 03:22
  • @Atlas: True, for NASM it's just `inc dword [rdi]` or `add dword [rdi], 1`. (Indeed they have the same effect, except for different handling of the carry flag which you don't care about. `inc` is one byte smaller and there may be very slight differences in performance, see https://stackoverflow.com/questions/36510095/inc-instruction-vs-add-1-does-it-matter if you are curious. – Nate Eldredge Dec 16 '21 at 04:43

1 Answers1

0

rax and eax are not separate registers. The eax register is the lower half of the rax register. Storing a value in the eax register will change the rax register. You will not update the integer being pointed at.

hs takeuchi
  • 126
  • 3
  • Yeah, that's why GCC11's asm (https://godbolt.org/z/P96hPG91e quoted in the question) reloads the pointer arg from its spill slot on the stack with `mov rax, QWORD PTR [rbp-8]`, after overwriting RAX by loading the value into EAX. (And using LEA to get an incremented copy in EDX). – Peter Cordes Dec 16 '21 at 03:18