2016-07-13 10 views
0

낮은 수준의 작업에 관심이 있으므로 여유 시간에 어셈블리를 배우고 있습니다. I tried running the code from this tutorial. SIGBUS 오류 - RaspberryPi의 ARM 프로세서 용 어셈블리

The code can be found here 아래

는 :

/****************************************************************************** 
* @file float.s 
* @brief simple example of scalar multiplication using the FPU 
* 
* Simple example of using the ARM FPU to compute the multiplication result of 
* two float values 
* 
* @author Christopher D. McMurrough 
******************************************************************************/ 

    .global main 
    .func main 

main: 

    LDR R0, =val1   @ load variable address 
    VLDR S0, [R0]   @ load the value into the VFP register 

    LDR R0, =val2   @ load variable address 
    VLDR S1, [R0]   @ load the value into the VFP register 

    VMUL.F32 S2, S0, S1  @ compute S2 = S0 * S1 

    VCVT.F64.F32 D4, S2  @ covert the result to double precision for printing 
    VMOV R1, R2, D4   @ split the double VFP register into two ARM registers 
    BL _printf_result  @ print the result 

    B _exit    @ branch to exit procedure with no return 

_exit: 
    MOV R7, #4    @ write syscall, 4 
    MOV R0, #1    @ output stream to monitor, 1 
    MOV R2, #21    @ print string length 
    LDR R1, =exit_str  @ string at label exit_str: 
    SWI 0     @ execute syscall 
    MOV R7, #1    @ terminate syscall, 1 
    SWI 0     @ execute syscall 

_printf_result: 
    PUSH {LR}    @ push LR to stack 
    LDR R0, =result_str  @ R0 contains formatted string address 
    BL printf    @ call printf 
    POP {PC}    @ pop LR from stack and return 

.data 
result_str:  .asciz  "Multiplication result = %f \n" 
exit_str:  .ascii  "Terminating program.\n" 
val1:   .float  3.14159 
val2:   .float  0.100 

내가하고있는 라즈베리 파이의 코드 컴파일 : 그것은 문제없이 컴파일

gcc -o float float.s 

을,하지만 난 그것을 실행할 때 나는 다음과 같은 오류가 발생합니다 :

Program received signal SIGBUS, Bus error.
0x00010428 in main()

나는 SIGBUS 오류의 원인에 대해 조사한 바 있으며, 여기에서 생각할 수있는 힌지는 잘못 정렬 된 메모리에 액세스하는 것으로 생각할 수 있지만 0x00010428 = 4 만 4로 나눌 수있는 10 진수의 66,600이므로 문제가 무엇인지 확실하지 않습니다.

processor: 0
model name: ARMv6-compatible processor rev 7 (v6l)
BogoMIPS: 2.00
Features: half thumb fastmult vfp edsp java tls
CPU implementer: 0x41
CPU architecture: 7
CPU variant: 0x0
CPU part: 0xb76
CPU revision: 7

Hardware: BCM2708
Revision: 0002

+1

main()의 0x00010428은 반드시 정렬됩니다.이 명령은 액세스되는 주소가 아닌 Signal을 발생시키는 명령입니다. -g로 다시 컴파일하고 gdb에서 실행합니다. 디버거는 오류가 – Tommylee2k

+0

인 곳을 표시합니다. printf 결과 함수는 스택을 64 비트 경계에 정렬하지 않습니다. 어쩌면 그게 맞습니까? –

+2

4로 나눌 수 있습니다. 아래쪽 두 비트 만 살펴 봐야합니다. 그들은 0x10428이 8 바이트로 끝나야합니다. 0b1000이므로 확실히 4 바이트 경계에 정렬됩니다. (십진수로 변환 할 필요 없음) –

답변

0

GDB 아래의 코드는 문제를 보여 실행 : 주소 0x2064e 4 바이트하지 않기 때문에

(gdb) b main 
Breakpoint 1 at 0x10424: file float.s, line 16. 
(gdb) r 
Starting program: /home/pi/a.out 

Breakpoint 1, main() at float.s:16 
16   VLDR S0, [R0]   @ load the value into the VFP register 
(gdb) p /x $r0 
$1 = 0x2064e 
(gdb) n 

Program received signal SIGBUS, Bus error. 
main() at float.s:18 
18   LDR R0, =val2   @ load variable address 

SIGBUS가 발생

cat/proc/cpuinfo 

나는 다음과 같은 얻을 실행

정렬. 이 문제를 해결하기 4.
한 가지 방법의 lengh하지 여러과의 선언 추적 문자열과 같은 문자열을하기 전에 부동의 선언을 이동하는 것입니다 때문에

val1val2 정렬 4 바이트는 없습니다 :

.data 
val1:   .float  3.14159 
val2:   .float  0.100 
result_str:  .asciz  "Multiplication result = %f \n" 
exit_str:  .ascii  "Terminating program.\n" 

이 수정 프로그램은 다음과 같이 인쇄합니다 :

+0

그건 흥미 롭 네요, 저 사람들이 그런 식으로 일한다는 것을 몰랐습니다. 그래서 저는 플로트와 문자열이 순차적으로 메모리 블록에 저장된다는 것을 알 수 있습니까? 그렇다면 4 바이트 정렬 될 때까지 다른 방법으로 문자열을 채울 수 있습니까? –