Home > Software design >  How does the stack differentiate between different number types?
How does the stack differentiate between different number types?

Time:09-18

I am trying to learn assembly and I’m having some trouble understanding memory allocation/retrieval on the stack.

When strings are allocated on the stack, the program knows to stop reading the string when it reaches a null terminating character /x00. With numbers however, there is no such thing. How does the program know the end of a number allocated on the stack, and how does it differentiate between different number types (short, long, int)? (I’m a bit new to this so please correct me on anything I may be misunderstanding!)

CodePudding user response:

Type (int vs. float vs. char * vs. struct foo) only really matters during translation, when the compiler is analyzing your source code and converting it to the appropriate machine code. That's when rules like "one of the operands of [] shall have pointer type and the other shall have integer type" and "the operand of unary * shall have pointer type" and "the operands of multiplicative operators shall have arithmetic type", etc., are enforced.

Assembly languages typically deal with bytes, words (2 bytes), longwords (4 bytes), etc., although some special-purpose platforms may have weird word sizes. The opcode addb1 adds the contents of two byte-sized entities, addl adds the contents of two longword-sized entities, etc. So when the compiler is translating your code, it uses the right opcodes for the object based on its declared type. So if you declare something as a short, the compiler will (typically) use opcodes intended for word-sized objects (addw, movw, etc.). If you declare something as int or long, it will (typically) use opcodes intended for longword-sized objects (addl, movl). Floating-point types are often handled with a different set of opcodes and their own set of registers.

In short, the assembly language "knows" where and how big things are by virtue of the opcodes the compiler specified.

Simple example - here's some C source code that works with an int and a short:

#include <stdio.h>

int main( void )
{
  int x;
  short y;

  printf( "Gimme an x: " );
  scanf( "%d", &x );

  y = 2 * x   30;

  printf( "x = %d, y = %hd\n", x, y );
  return 0;
}

I used the -Wa,-aldh option with gcc to generate a listing of the assembly code with the source code interleaved, giving me

GAS LISTING /tmp/cc3D25hf.s             page 1


   1                    .file   "simple.c"
   2                    .text
   3                .Ltext0:
   4                    .section    .rodata
   5                .LC0:
   6 0000 47696D6D      .string "Gimme an x: "
   6      6520616E 
   6      20783A20 
   6      00
   7                .LC1:
   8 000d 256400        .string "%d"
   9                .LC2:
  10 0010 78203D20      .string "x = %d, y = %hd\n"
  10      25642C20 
  10      79203D20 
  10      2568640A 
  10      00
  11                    .text
  12                    .globl  main
  14                main:
  15                .LFB0:
  16                    .file 1 "simple.c"
   1:simple.c      **** #include <stdio.h>
   2:simple.c      **** 
   3:simple.c      **** int main( void )
   4:simple.c      **** {
  17                    .loc 1 4 0
  18                    .cfi_startproc
  19 0000 55            pushq   %rbp
  20                    .cfi_def_cfa_offset 16
  21                    .cfi_offset 6, -16
  22 0001 4889E5        movq    %rsp, %rbp
  23                    .cfi_def_cfa_register 6
  24 0004 4883EC10      subq    $16, %rsp
   5:simple.c      ****   int x;
   6:simple.c      ****   short y;
   7:simple.c      **** 
   8:simple.c      ****   printf( "Gimme an x: " );
  25                    .loc 1 8 0
  26 0008 BF000000      movl    $.LC0,            
  • Related