There is such a c ++ function

extern int** GetSubOrders(int* order); 

It is necessary to file the body in the assembler module for nasm under ubuntu. The question is: how to work with pointers in this case? those. get an order, pull values ​​out of it, push by sub-arrays and return a pointer to an array of pointers? Interested in asm code, thanks.

It is clear that order is the address of the first element of the array, but the difficulty is how to get its values ​​from the stack and thus scroll through the entire array. Return the int ** also through the stack, but put there only the address on the array of addresses, which in turn were located somewhere in the variable, or arrange all the addresses of the sub-arrays?

  • if order is an array, then the size of the array must be passed to the function or an "final element" must be agreed. In another way, of course, it is possible, but this is all very compilable and very important. - KoVadim
  • @KoVadim interested in the mechanism itself. all necessary assumptions regarding the addition of new variables to the function or other additional information can be made. - persifal
  • OK. in order will be a pointer (address) to the first (zero) element. Since pointers are most likely 4 bytes, then adding 4 to this address will get a pointer to the next element. - KoVadim
  • Why did you decide to return something through the stack? In most calling conventions (by the way, you determine which convention you use) the return value is in eax. If the value is greater than 4 bytes, then it is put on the current top of the stack and in eax returns a pointer to this point in the stack. int ** should get into eax if you have 4-byte pointers - Mike
  • one
    Write the desired code in c ++ and clearly indicate in the question what code generated by the compiler is not sufficient in your case. Here is an example of a function that works with an array without a stack (returns a pointer to the largest element in the passed array): ++first in assembler as addq $4, %rdi might look like where first is int* . - jfs

1 answer 1

First you need to decide on the calling convention , for example, take __fastcall , then if you have int 4 bytes, then ecx = order . Then [ecx] is the zero element of the array. You can start a loop with edi , for example, to list all the elements of an array through the [ecx + 4*edi] . If you have x64 mode, and not x86 , then there are other calling agreements, and the principle is slightly different. If I remember correctly (you can clarify here ), the first parameter is passed through rcx , then rdx , r8 and r9 . Passing through the array is the same - through [rcx + 4*rdi] , when rdi = 0, 1, 2 ...

Only one trouble - the name of the function, you do not know it. You can learn how to function with a linker error. When you start linking, an error will come out that the function is such and such with the name of какое-то-название certain какое-то-название defined, but not implemented. (For example, in one of my projects the name is so scary ?add@AddAsm@@YIIPAIPBIII@Z , although the original function was called AddAsm::add ). That is the name and you will need to enter in the assembly code. Below is pseudo-code (almost nasm), roughly similar to what you need (more specifically, I will not show it, because I don’t provide a higher level of specifics than the specifics of the question). By the way, the word extern not needed.

 [BITS 32] global какое-то-название-функции ; Тут декларируется функция section .code какое-то-название-функции: ; Тут точка входа в функцию. push edi ; __fastcall обязан заботится о сохранении edi, esi и ebx xor edi, edi .loop: mov edx, [ecx + edi*4] ... Что-то делаем с edx ... lea edi, [edi + 1] ; ++ edi cmp edi, некое-число ; Сколько итераций нужно jne .loop pop edi mov eax, Бла-бла ; Это результат работы функции, передаётся через eax. ret 0 ; Выход без корректировки стека 

Starting from this, try to solve your problem yourself.

  • one
    In order not to suffer from name mangling, you need to wrap the function declaration in the c ++ code in an extern "C" { ... } block. - insolor
  • @insolor, and how then will the parameters be transmitted? - Zealint
  • one
    Just like without this block. This block affects how the function name will be represented in the object file. Mangling is needed only if there are several functions with the same name, but different parameters. If there is only one such function, then mangling does not make much sense. In any case, what happened to him, that without him, in fact, the number of parameters and their type in the compiled executable file is not checked in any way. - insolor
  • Those. The number and type of parameters is of course checked, but at the stage of compiling into an object file, by the way the declaration of the external function looks. It is important for Linker that there are no two objects with the same name, and he does not check the parameters of the functions. - insolor