Получение граничной ошибки адреса при выполнении нормально, но отлично работает с GDB - PullRequest
0 голосов
/ 25 января 2020

Я работаю над простым калькулятором, который выполняет следующие операции: +, -, x (*), /, ^; Я уже проверил каждую операцию, но если я использую '^', она завершается сигналом SIGSEGV (Ошибка границы адреса, код состояния 139), но отлично работает с GDB. В строке, отмеченной '!!!!!!!' что-то происходит Если после этой команды я выполнил команду jmp, она не работает и возвращает код выхода 139. Если я прыгаю до '!!!!!!' Строка для выхода выполняется успешно. Таким образом, должна быть проблема с этим разыменованием, но только для '^' и только без GDB.

.code32
.section .data
newline: .ascii "\n"
lngth = . - newline
 bplus: .ascii "(+"
 lenbplus = . - bplus
 b: .ascii ")"
 lenb = . - b
 ws: .ascii " " 

isNeg: .long 0
op1: .long 0            # 1st operand
op2: .long 0            # 2nd operand
count: .long 0
remainder: .long 0
add: .ascii "+"
sub: .ascii "-"
mul: .ascii "x"
div: .ascii "/"
pot: .ascii "^"
operator: .ascii ""     # operator
.section .text

.globl _start

_start:
addl $8, %esp           # move ESP to first argument of stack
movl (%esp), %esi       # move content of ESP to ESI 
movl %esi, op1          # move ESI to global variable op1
addl $4, %esp           # move ESP on stack forward

movl (%esp), %esi       # move content of ESP to ESI
mov (%esi), %eax        # !!!!!!!

#jmp _exit
movb %al, operator

addl $4, %esp           # move ESP on stack forward
movl (%esp), %esi       # move content of ESP to ESI
movl %esi, op2          # move ESI to global variable op2

pushl op1               # push first operand onto the stack
call convertOperand     # call function to convert operand from .ascii to .long
movl %eax, op1          # move return value of function to global variable

pushl op2
call convertOperand     # call function to convert  second operand from .ascii to .long
movl %eax, op2          # move return value of function to global variable

pushl op1               # push operand 1 onto the stack
pushl op2               # push operand 2 onto the stack

movb operator, %al      # move the input operator to AL (EAX)

## operand is + ##
movb add, %bl
cmpb %al,%bl
je _add
## operand is - ##
movb sub, %bl
cmpb %al,%bl
je _sub
## operand is * ##
movb mul, %bl
cmpb %al,%bl
je _mul
## operand is / ##
movb div, %bl
cmpb %al,%bl
je _div
## operand is ^ ##
movb pot, %bl
cmpb %al,%bl
je _pot


_add:
call addition
jmp _printResult
_sub:
call subtraction
jmp _printResult
_mul:
call multiplication
jmp _printResult
_div:
call division
jmp _printResult
_pot:
call potentation
jmp _printResult


.type addition, @function
addition:
pushl %ebp              # save old base pointer
movl %esp, %ebp         # make stack pointer the new base pointer
subl $4, %esp           # reserve space for local variable

movl 12(%ebp), %ecx     # move 2nd operand to register
movl 8(%ebp), %edx      # move 1st operand to register
addl %ecx, %edx         # perform addition
movl %edx, -4(%ebp)     # save result to local variable
movl -4(%ebp), %eax     # put lcal variable to EAX (function return value)

movl %ebp, %esp         # restore old ESP (stack pointer)
popl %ebp               # restore old EBP (base pointer)
ret                     # return from function (pops return address 
                        # and moves it into EIP, so execution
                        # continues where we left before calling the function
.type subtraction, @function
subtraction:
pushl %ebp
movl %esp, %ebp
movl 12(%ebp), %eax
movl 8(%ebp), %edx
subl %edx, %eax
jc _negResult
_posResult:
    movl %ebp, %esp
    popl %ebp
    ret
_negResult:
    movl 12(%ebp), %edx
    movl 8(%ebp), %eax
    subl %edx, %eax
    incl isNeg
    jmp _posResult



.type multiplication, @function
multiplication:
pushl %ebp
movl %esp, %ebp
movl 12(%ebp), %eax
movl 8(%ebp), %edx
imul %edx
movl %ebp, %esp
popl %ebp
ret

.type division, @function
division:
pushl %ebp
movl %esp, %ebp
movl 12(%ebp),%eax
movl 8(%ebp), %ecx

cmpl $0, %ecx
je _exit_err


movl $0 , %edx
divl %ecx
movl %edx, remainder

movl %ebp, %esp
popl %ebp
ret

.type potentation, @function
potentation:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %edx
movl %edx, count
movl 12(%ebp), %edx
movl %edx, %eax

cmpl $0, count
je _ResultIsOne

_calcPot:
    imull %edx, %eax
    decl count
    cmpl $1, count
    jg _calcPot
    jmp _returnResult


_ResultIsOne:
    movl $1, %eax

_returnResult:
    movl $0, count
    movl %ebp, %esp
    popl %ebp
    ret

.type convertOperand, @function  #converts a .ascii to .long
convertOperand:
pushl %ebp              # save old base pointer
movl %esp, %ebp         # make stack pointer to new EBP
subl $4, %esp           # reserve space for local variable

movl 8(%ebp), %ecx      # move argument (operand) to register
movl (%ecx), %edx       # dereference the argument


movb %dl, %bl           # move first byte to BL (EBX)
subl $0x30, %ebx        # subtract the 0x30 from ascii value to get numeric value
movl %ebx, %eax         # move result to EAX

incl %ecx               # increment the reference by one byte
movl (%ecx), %edx       # dereference the value
movb %dl, %bl           # move first byte to BL

cmpb $0, %bl            # compare if byte is a null termination
je _nullTerminated

imul $10, %eax          # multiply EAX with 10
subl $0x30, %ebx        # substract 0x30 from ascii value to get numeric value
addl %ebx, %eax         # add numeric value to EAX
incl %ecx               # increment the reference by one byte

### loop until no single digit is left of the number ###
_loop:
movl (%ecx), %edx       # dereference value to EDX
movb %dl, %bl           # move first byte to BL
cmpb $0, %bl            # compare if null termination or not

je _nullTerminated

imul $10, %eax          # multiplay EAX with 10
subl $0x30, %ebx        # substract 0x30 from ascii value to get numeric value
addl %ebx, %eax         # add numeric value to EAX
incl %ecx               # increment reference by one byte
jmp _loop               # back to loop head


_nullTerminated:
movl %ebp, %esp
popl %ebp
ret

### print the result of operation ###
_printResult:
### result already saved in EAX due to operator-function ###
movl %edx, %ebp
cmpl $1, isNeg
je  _printMinus
### print sinle digits of result ###
_getSingleDigits:
    movl $0, %ecx       # sets 0 to ECX
    movl $0, %edx       # sets 0 to EDX
    movl $10, %ebx      # moves number 10 to EBX
    divl %ebx           # divide by EBX (10) to get a single digit
    movl %edx, %ecx     # save remainder in ECX
    addl $0x30, %ecx     # adds 0x30 to the digit to get right ascii-code
    pushl %ecx          # push the correct ascii code of the number onto the stack
    incl count          # increment count
    cmpl $0, %eax       # compare if dividend equals 0
    jne _getSingleDigits           #jump to of _loop id dividend is not 0
    ### pop the digits from the stack ###
    _pop:
        movl %esp, %ecx # get single digit from stack
        decl count      # derement count
        movl $1, %edx   # EDX message length
        movl $1, %ebx   # EBX = file descriptor (1 = stdout)
        movl $4, %eax   # syscall number (4 = write)
        int $0x80       # call kernel by interrupt
        popl %ecx       # pop the stack so the esp is decremented
        cmpl $0, count  # if count is not 0 -> jump to _pop
        jne _pop
### check if Remainder is 0 ###
cmp $0, remainder
jg _printRemainder
### print a newline ###
_new:
movl $lngth, %edx
movl $1, %ebx
movl $newline, %ecx
movl $4, %eax
int $0x80
### exit programm succesfully ###
_exit:
movl $0, %ebx
movl $1, %eax
int $0x80
### exit programm with error code 1 ###
_exit_err:
movl $1, %ebx
movl $1, %eax
int $0x80
### print a '-' ##
_printMinus:
movl %eax, %ebp #store result in EBP inorder to print Minus
movl $1, %edx
movl $1, %ebx
movl $sub, %ecx
movl $4, %eax
int $0x80
movl %ebp, %eax #back shift result to EAX
jmp _getSingleDigits
### print the whole Remainder ##
_printRemainder:
### print ' '(whitespace ###
movl $1, %edx
movl $1, %ebx
movl $ws, %ecx
movl $4, %eax
int $0x80
### print '(+' ###
movl $lenbplus, %edx
movl $1, %ebx
movl $bplus, %ecx
movl $4, %eax
int $0x80
### print actual Remainder ###
movl $remainder, %eax
movl (%eax), %eax
_getRemainderDigits:
    movl $0, %ecx       # sets 0 to ECX
    movl $0, %edx       # sets 0 to EDX
    movl $10, %ebx      # moves number 10 to EBX
    divl %ebx           # divide by EBX (10) to get a single digit
    movl %edx, %ecx     # save remainder in ECX
    addl $0x30, %ecx     # adds 0x30 to the digit to get right ascii-code
    pushl %ecx          # push the correct ascii code of the number onto the stack
    incl count          # increment count
    cmpl $0, %eax       # compare if dividend equals 0
    jne _getRemainderDigits           #jump to _getRemainderDigits if dividend is not 0
    ### pop the digits from the stack ###
    _pop1:
        movl %esp, %ecx # get single digit from stack
        decl count      # derement count
        movl $1, %edx   # EDX message length
        movl $1, %ebx   # EBX = file descriptor (1 = stdout)
        movl $4, %eax   # syscall number (4 = write)
        int $0x80       # call kernel by interrupt
        popl %ecx       # pop the stack so the esp is decremented
        cmpl $0, count  # if count is not 0 -> jump to _pop
        jne _pop1
### print ')' ###
movl $lenb, %edx
movl $1, %ebx
movl $b, %ecx
movl $4, %eax
int $0x80
jmp _new
...