0

I am writing an intel x86 assembly program to compute logarithms using a log table. I call the assembly function in a c program. I don't want to move all the values in the log table to memory every time i call. I'm new to assembly on a non-simulated processor, so I'm not even sure where I'm allowed to store it. 20,000 32-bit integers.

How can I store a "large" amount of data once at the beginning of a c program, so that I can access it in an assembly routine? If i put it in the .data section, is it moved to memory every time i call the actual function?

Edit: this is how i call the function

#include <stdio.h>
extern int doIt(float) asm("doIt");
int main(){
    printf("%d\n", doIt(7.0));
    printf("%d\n", doIt(4.0));
    ... //more calls of the sort
}

Not sure if the c code is completely correct. In doIt i need to access the mentioned table repeatedly.

Max Fest
  • 45
  • 1
  • 4
  • 1
    the .data section is always in memory... So are all the other sections for that matter (except the ones specifically marked to not be in memory) – user253751 Jun 14 '18 at 22:28
  • 1
    Can you show us an example of what you mean by “move all the values to memory?” If you put some data into the `.data` section, it is loaded to memory on program start and remains there until the program ends. I'm not sure what kind of move you were thinking about. – fuz Jun 14 '18 at 22:31
  • 1
    Can you post code? Are you writing C code with inline asm? – Dario Rodriguez Jun 14 '18 at 22:32
  • 1
    Put `const int32_t logtable[] = { 0, 1, 2, 2, 3, 3, 3, ... };` at global scope. Then use that `logtable` symbol name in asm. Hint, look at compiler output to see how compilers implement arrays with static storage. [How to remove "noise" from GCC/clang assembly output?](https://stackoverflow.com/q/38552116). (And BTW, those are base-2 logs of 1, 2, 3, 4, ..., which you should calculate on the fly with `bsr` instead of using a LUT at all. Presumably you have some other use-case.) – Peter Cordes Jun 14 '18 at 22:36
  • 1
    In practice data in the `.data` segment may not be loaded into memory until the program tries to access it or other data on the same page, but it should stay in memory after that unless it gets paged out (which probably shouldn't be happening while the program is running in this context). On a typical system an ~80KB table shouldn't have any trouble remaining in memory, though its data may move in and out of various cache levels. – SevenStarConstellation Jun 14 '18 at 22:38
  • @SevenStarConstellation exactly what i hoped to find out! – Max Fest Jun 14 '18 at 22:43
  • @Peter Cordes that also seems like a good solution, thanks. I specifically have to implement a log table log calculation and then compare to existing c functions. – Max Fest Jun 14 '18 at 22:46
  • I actually think that you are pushing things to be complicated. There is no need for the ASM routine at all. But if you just want to do it as a hobby, then it seems to me a better choice to write inline asm. If not, just declare the array and import the symbol. – Dario Rodriguez Jun 14 '18 at 22:54
  • @SevenStarConstellation: My suggestion was to make the data compile-time constant, so the compiler can put it in the `.rodata` section (which will be linked into the text segment). But yes it would be demand-paged like you describe. The OP's text description (but not code) sounds like they might want the C program to generate the table on the fly, though, in which case you'd use `int32_t logtable[20000];` so the compiler could put it in the `.bss`. You only want stuff in `.data` when it needs to be read/write but have a non-zero initial value. – Peter Cordes Jun 15 '18 at 05:02
  • @Peter Cordes: You're certainly correct: if the table is precomputed by the time of compilation it would be better included as read-only data instead of in the `.data` segment. I didn't get the impression from the question that the table was to be generated at runtime, but it is helpful that you've noted a better approach for that case too. – SevenStarConstellation Jun 15 '18 at 05:29
  • @SevenStarConstellation: I was looking at the *How can I store a "large" amount of data once at the beginning of a c program ...* phrase. If the data is *already* stored in `.rodata` before the C program runs, that doesn't quite match the phrasing. If the C program itself does the storing, rather than the compiler ahead of time, then you want to compute it on the fly, not copy it from somewhere. – Peter Cordes Jun 15 '18 at 06:30
  • BTW, data which are write-able, yet they require initial value after binary execution (`.data`) are usually source of bugs, because people often forget to reinitialize their values for second usage (which was not originally planned any way)... so generally you shouldn't need anything in `.data`, `.rodata` and `.bss` should be enough for clean code which does init all it's variables properly. `.data` is like optimization kind of thing, when you want to avoid the initialization code at runtime, and price is higher likeliness of introducing some bug. – Ped7g Jun 15 '18 at 07:07
  • @DarioRodriguez i am doing this for a uni project, they explicitly stated no inline assembler, limited the number of commands i am allowed to use, and as far as I know I am not meant to write any code anywhere outside of my assembler routine aside from a test program. – Max Fest Jun 15 '18 at 07:51

1 Answers1

1

To give it an answer:

#include <stdint.h>

const int32_t table[10]; /* .rodata */

int32_t table[10]; /* .bss */

/* 
 * However, if you initialize with any (nonzero) values
 * it goes to:
 */

 int32_t table[10]={
    0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
    0x00000000,0x00000000,0x00000000,0x00000000,0xaaaaaaaa
 }; /* .data */

 const int32_t table[10]={
    0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
    0x00000000,0x00000000,0x00000000,0x00000000,0xaaaaaaaa
 }; /* .rodata */

About the sections: .data and .rodata are stored in the object file and may not be loaded to RAM unless you need to use them, or anything contained into the same page -maybe you can change this behaviour with a linker script, I don't know-, and .bss section doesn't actually store any data, that is why once you initialize the variable, it moves to .data and gets it's image stored into the object file. Most compilers will ignore initialization to zero because the .bss variables do not have their image stored into the object file, so the loader fills their space to zero anyways when it loads the program.

Then, when you compile the object, you can import the symbol name from your ASM routine.

Dario Rodriguez
  • 802
  • 6
  • 15