3

I intend to do this in C:

#include<stdio.h>
int main() {
  int arr[5];
  arr[0] = 5;
  arr[1] = 0;
  arr[2] = 1;
  arr[3] = 3;
  arr[4] = 4;
  int max = 0;
  for(int i = 0;i < 5;i++)
    if(max < arr[i])
      max = arr[i];
  printf("%d\n", max);
  return 0;
}

This is my code link: array_max.s. This is my assembly code in AT&T format :

.data

.text
.globl _start
_start:
  movl $5, -20(%ebp)
  movl $0, -16(%ebp)
  movl $1, -12(%ebp)
  movl $3, -8(%ebp)
  movl $4, -4(%ebp)
  movl $0, %ecx
  movl $5, %eax
  loop:
    cmp $0, %eax
    je terminate
    cmp %ecx, -20(%ebp,%eax,4)
    jg assign
    jmp loop


terminate:
  movl $4, %eax
  movl $1, %ebx
  movl $1, %edx
  int $0x80
  movl $1, %eax
  int $0x80
  ret

assign:
  movl -20(%ebp,%eax,4), %ecx
  ret

I am having a segmentation fault on the very first instruction movl $5, -20(%ebp). I am new to this, please help.

JFMR
  • 23,265
  • 4
  • 52
  • 76
as2d3
  • 802
  • 2
  • 10
  • 27
  • 2
    When `_start` is called, what is `%ebp` pointing to? You never set up your stack-frame. – Some programmer dude Aug 24 '17 at 09:04
  • not an expert but shouldn't `%ebp` be initialized to some valid memory? reserve memory in the stack and write to it? – Jean-François Fabre Aug 24 '17 at 09:05
  • @Jean-FrançoisFabre No, it's not. In assembly no magic happens, only things you set/reserve/acquire are available. – Ped7g Aug 24 '17 at 09:06
  • I suppose that the system provides you for the arguments in some registers though. Otherwise, I agree with the rest, it's just that I'm not a big x86 expert... – Jean-François Fabre Aug 24 '17 at 09:09
  • @Jean-FrançoisFabre depends which system, and what ABI, etc... OP didn't specify anything of that, but as he's using `_start:` label, this is not ordinary function, but app entry point, so the OS barely sets up anything, the stack is very likely legit and of reasonable size, and there's certainly some mechanism to provide arguments, but anything else like values in registers is probably not defined (or for portability reasons it's better to rely on OS values in minimal possible way, like in this case only stack is needed to allocate temporary array for toying around, no need to read args). – Ped7g Aug 24 '17 at 09:14
  • 1
    @Ped7g: OP did specify 32-bit Linux and is using the `int 0x80` system call ABI, so it's very clear that this code is targeting the x86-32 System V psABI. In `_start`, `%esp` = stack, with argc, argv[] contents, and envp on the stack. Most other registers = garbage (or in Linux, = 0). @Abhishek: the debugger should have showed you that `%ebp`=0. – Peter Cordes Aug 24 '17 at 11:46
  • @Jean-FrançoisFabre: Links to ABI docs in https://stackoverflow.com/tags/x86/info. (And see my previous comment). – Peter Cordes Aug 24 '17 at 11:47
  • @PeterCordes yeah, code looks as linux 32b, but OP didn't specify that, so who knows, maybe he managed to compile that with djgpp under windows, and it will crash few lines later even after fixing `ebp`... either way, I'm not in a mood to provide any full-answer AT&T code, just reading it is causing me enough pain. :) So only hints from me. – Ped7g Aug 24 '17 at 11:58
  • @Ped7g: Look at the tags: `[linux]` and `[x86]` (which some people think means 32-bit specifically, rather than just x86 in general). Edit: oops, `[linux]` was added later by someone else. Still, the OP's other question (about how to write a loop) made it clear it's Linux. But yeah, this is the kind of thing you ask your instructor. Way too basic to be fun to answer. – Peter Cordes Aug 24 '17 at 12:01

1 Answers1

5

I am having a segmentation fault on the very first instruction movl $5, -20(%ebp).

You are not allocating any space on the stack for arr (i.e.: int arr[5]):

pushl %ebp
movl %esp, %ebp
subl $20,%esp //<--- memory allocation

In order to deallocate the memory allocated on the stack by restoring the previous stack frame, use the leave instruction just before ret.

JFMR
  • 23,265
  • 4
  • 52
  • 76
  • Hey, in my terminate label, I am trying to print the value stored in ```%ecx``` on the terminal. But it is not printing anything. Can you help printing the value in ```%ecx```? – as2d3 Aug 24 '17 at 09:44
  • @AbhishekAgrawal at the moment of executing `cmp $0, %eax`, the register `eax` is always `5`. Therefore, the conditional jump just after the comparsion is never performed and the label `terminate` is never reached. – JFMR Aug 24 '17 at 10:01
  • Yes, this is my new code which works fine but no printing. Link : http://collabedit.com/yc4x8. – as2d3 Aug 24 '17 at 10:08
  • @AbhishekAgrawal `ecx` must contain the *address* of what you want to print. Do `push %ecx` and `movl %esp, %ecx` before `int $0x80`. – JFMR Aug 24 '17 at 10:22
  • Also `movl $4, %edx` (for sending 4-bytes to `stdout`). It will print the character representation of those 4-bytes, not the numerical value. Otherwise consider using `printf` instead. – JFMR Aug 24 '17 at 10:27
  • 2
    @AbhishekAgrawal: See [Printing an integer as a string with AT&T syntax on Linux](https://stackoverflow.com/questions/45835456/printing-an-integer-as-a-string-with-att-syntax-on-linux) – Peter Cordes Aug 24 '17 at 11:41