NASM SEGMENTATION FAILURE

Asked

Viewed 117 times

0

Code update: I followed the tips and tried to stop the loop in the update section. I’m still working on the segmentation failure, however. And I need to check this loop, I don’t think it’s quite right....

Hello, I’m writing code to perform a series of sequential tasks in NASM syntax. At first I could not even compile, but now although Compile, and run Linker, when running the program in the terminal I get the message "Segmentation failure (image of the saved kernel)". Since I’m terrible at this, and I’m just beginning to understand what Assembly’s logic is, I can’t find the error. Anybody got any tips? It’s for linux, but in the slides I took from some lessons on the internet, in Ubuntu people use this mov eax,1 - int 80h as a system call.

section .data

        array   DB 30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,82,30,30,30
        divisor DB 10
        result  DW 0

section .text                                                                   
    global _start
    
_start:
        
        xor ax,ax
        xor cx,cx
        xor bl,bl
        
        mov si,[array+0]
        mov cx,20                                               
        mov bl,[si]                                                 
        
loopx:
        cmp [si],bl                                 
        jle update                                  

resume:
        inc  si                                                         
        loop loopx                                      
        
update:
        mov bl,[si]
        cmp [array+80],bl
        je  c_soma                          
        jmp resume                                  
        
        xor bh,bh                   
        mov [result],bx     
        mov ax,[result]         
        mov bl,[divisor]        
        div bl                  
        
        mov bl,al                       
        
        jmp c_soma          
        
        
body_soma:
        sub al,1    
        add bl,al   
        jmp c_soma  
        
        
c_soma:
        cmp al,0            
        jne body_soma   

        mov eax,1
        int 0x80

the goal is to make a sequence of actions: first go through the vector of 20 positions and find the lowest value by updating the register. When you finish going through the vector, you should register only the digit of the ten, so the division by 10, and finally make an arithmetic sum for this found ten. I chose all the same with the ten of 3 so I could have something to add 3+2+1 to, so Dec. It does not return to the screen, because I use seeReturn.sh to see the result of the operation. Yes, he seems to have done nothing, but the idea is to operate values, vectors and addresses.

in terminal use nasm -f elf -o nomedoarquivo.o nomedoarquivo.asm to compile and ld -m elf_i386 -s -o nomedoarquivo nomedoarquivo.o to the Linker.

UPDATING THE QUESTION: has any way of traversing the vector from the first position without setting pointer? I tried offset array but gave syntax error too.

  • 2

    What would be your goal with this program? it has some accounts, but does not do any I/O operation - so even if it works, it will end without looking like it did anything.

  • another - it’s for Windows/DOS right? I vaguely remember the int 80h with code "1" to end the program. Need to mark, because on Mac and Linux would be different.

  • 1

    the goal is to make a sequence of actions: first go through the vector of 20 positions and find the lowest value by updating the register. When you finish going through the vector, you should register only the digit of the ten, so the division by 10, and finally make an arithmetic sum for this found ten. I chose all the same with the ten of 3 so I could have something to add 3+2+1 to, so Dec. It does not return to the screen, because I use seeReturn.sh to see the result of the operation. Yes, he seems to have done nothing, but the idea is to operate values, vectors and addresses.

  • 1

    It’s for linux, but in the slides I took from some lessons on the internet, in Ubuntu people use this mov eax,1 - int 80h as a system call.

  • in the terminal use nasm -f Elf -o filename. the filename.asm to compile and Ld -m elf_i386 -s -o filename filename filename. o for Linker. Therefore global _start.

1 answer

0


I’m rusty, or I’d risk a more assertive response - but you see the mov si,[array+0] - this moves the Value found at the address "array + 0" to the register SI (the value "30") - and mov bl, [si] you are using the SI value as a pointer (memory address) - this alone would cause segfault.

First try then - exchange that instruction for mov si, array+0.


Update - it took but I found - as you know, the code you are writing is basically 16bit Assembler (AX registers, it has 16bit width, al and ah are two 8bit halves, etc)... this is from the 8086 time - and there, there is a serious addressing problem - to address over 2 16 bytes of memory (64KB) this architecture made use of the "segment registers" (DS, ES, CS and SS) to compose the final address in up to 1MB of memory.

With the 32bit architecture of the 386, it became possible to write programs addressing memory directly, without the use of these segment registers (registers could address up to 4GB of memory directly - the S.O. can use internal registers to manage intermediate memory tables to get to the actual address and address more than 4GB) -

But, digression aside, by default the elf32 format of Linux assumes that its code is 32bit, and will add a constant value in all its memory addresses when compiling - this value by default is 0x08048000 - so when trying to load the address of "array" in SI it tries to put the array address + 0x08048000 - which does not fit in SI Why is it only a 16bit time logger of the 8086.

The whole problem then resolves itself instead of using SI you use ESI as address logger - this is the 32bit version of SI (the bottom 16 bits are SI). With the nasm in Linux we are writing code that will run in the 32bit "protected mode", and even if we can limit the algorithm and instructions to the legacy 16 bit registers, we can make use of the will of all the 32bit registers of this architecture.

Well - I broke a "knot" in your logic - it’s easier to follow, and I put an unconditional jump after instruction loop to the point where the sum is made.

The Section date in the end was something else that "happened" in my attempts to hit.

section .text
  global _start
_start:
        
        xor ax,ax
        xor cx,cx
        xor bl,bl
       
        mov esi, array
        mov cx,20                                               
        mov bl,[esi]                                                 
loopx:
        cmp [esi],bl                                 
        jg not_update                                  

        mov bl, [esi]
not_update:

        inc  si                                                         
        loop loopx                                      
        
end_loop:        
        xor bh,bh                   
        mov [result],bx     
        mov ax, bx
        mov bl,[divisor]        
        div bl                  
        
        mov bl,al                       
        
        jmp c_soma          
        
        
body_soma:
        sub al,1    
        add bl,al   
        jmp c_soma  
        
        
c_soma:
        cmp al,0            
        jne body_soma   

        mov eax,1
        int 0x80

section .data
        array   DB 30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,82,30,30,30
        divisor DB 10
        result  DW 0

And last but not least, link to the answer on SOEN where I was able to understand the issue of addressing:

https://stackoverflow.com/a/35000389/108205

  • It didn’t work, but I think it did because of the syntax. If I use the pointer as an address, it gives Mismatch in the size of the source and destination registers (2 bits - 8 bits).

  • the "si" register is 16 bits wide - I’ve tracked your entire program now, and compiled a "hellor world" here for me - I found another problem: when the loop He doesn’t "know" that he has to go to body_soma - will continue in the next statement - and will arrive in the jmp resume - basically an infinite loop.

  • Thanks!!!! After your explanation, I think I will need to study a little more this logic between 16-32 bits.... A very important part was this solution to the loop, because I was fixed in the if-not and always ended up falling into the infinite loop. Thank you very much!

  • it is important to understand that the "loop" statement is not something automatic like for or while in C - is the equivalent dec cx; jnz <alvo> when CX reaches 0, continues in the instruction below.

  • uses 32 bits - I’ve seen that in the last 15 or 20 years, the story of calling int 80h also lagged behind, even at 32bit - the correct is to use the instruction sysenter: http://articles.manugarg.com/systemcallinlinux2_6.html (is that systenter is a "novelty" of the Pentium II, did not exist in the original 386)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.