堆栈2

今天在搞arm汇编,终于明白它的堆栈到底是个怎么回事

先贴上代码:

USR_STACK_LENGTH EQU 64
SVC_STACK_LENGTH EQU 0
FIQ_STACK_LENGTH EQU 16
IRQ_STACK_LENGTH EQU 64
ABT_STACK_LENGTH EQU 0
UND_STACK_LENGTH EQU 0

  AREA Example5,CODE,READONLY
  ENTRY
  CODE32
START MOV R0,#0
      MOV R1,#1
      MOV R2,#2
      MOV R3,#3
      MOV R4,#4
      MOV R5,#5
      MOV R6,#6
      MOV R7,#7
      MOV R8,#8
      MOV R9,#9
      MOV R10,#10
      MOV R11,#11
      MOV R12,#12

      BL InitStack

      ;打开IRQ中断(cpsr寄存器的I位零位)
      MRS R0,CPSR
      BIC R0,R0,#0X80
      MSR CPSR_cxsf,R0

      ;切换到用户模式
      MSR CPSR_c,#0XD0
      MRS R0,CPSR

      ;切换到管理模式
      MSR CPSR_c,#0XDF
      MRS R0,CPSR

HALT B HALT
InitStack
      MOV R0,LR
      ;设置管理模式堆栈
      MSR CPSR_c,#0xd3
      LDR SP,StackSvc
      ;设置中断模式堆栈
      MSR CPSR_c,#0xd2
      LDR SP,STackIrq
      ;设置快速中断模式堆栈
      MSR CPSR_c,#0XD1
      LDR SP,STackFiq
      ;设置中止模式堆栈
      MSR CPSR_c,#0XD7
      LDR SP,STackAbt
      ;设置未定义模式堆栈
      MSR CPSR_c,#0XDB
      LDR SP,STackUnd
      ;设置系统模式
      MSR CPSR_c,#0XDF
      LDR SP,StackUsr

      MOV PC,R0
StackUsr DCD UsrStackSpace+(USR_STACK_LENGTH-1)*4
StackSvc DCD SvcStackSpace+(SVC_STACK_LENGTH-1)*4
STackIrq DCD IrqStackSpace+(IRQ_STACK_LENGTH-1)*4
STackFiq DCD FiqStackSpace+(FIQ_STACK_LENGTH-1)*4
STackAbt DCD AbtStackSpace+(ABT_STACK_LENGTH-1)*4
STackUnd DCD UndStackSpace+(UND_STACK_LENGTH-1)*4

;分配堆栈空间
  AREA MyStacks,DATA,NOINIT,ALIGN=2
UsrStackSpace SPACE USR_STACK_LENGTH*4
SvcStackSpace SPACE SVC_STACK_LENGTH*4
IrqStackSpace SPACE IRQ_STACK_LENGTH*4
FiqStackSpace SPACE FIQ_STACK_LENGTH*4
AbtStackSpace SPACE ABT_STACK_LENGTH*4
UndStackSpace SPACE UND_STACK_LENGTH*4
 END

 再贴上两幅图

 

注意上面红色圈住的部分。上面的图说明以下以点:

1.程序在0x0000808C处结束

2.程序后面的伪代码诸如:

StackUsr DCD UsrStackSpace+(USR_STACK_LENGTH-1)*4
StackSvc DCD SvcStackSpace+(SVC_STACK_LENGTH-1)*4

它们的地址是紧跟着程序末尾的

3.LDR SP,StackSvc是将StackSvc这个标号处的内容给sp,如图StackSvc标号的地址为0x8094但是其内容是

由下面的语句决定:

StackSvc DCD SvcStackSpace+(SVC_STACK_LENGTH-1)*4决定

SvcStackSpace标号的地址为0x81a8,所以StackSvc的内容为0x81a4

由上面三点认识,可以得出如下结论:各个模式下的堆栈指针不是一个固定的值。而是由程序

编译后根据程序大小来决定的。我们可以规定堆栈的大小,初如化的时候只需要将堆栈指针

放到合适的位置即可。在正式的程序运行时,可能我们所用的栈可能比规定的堆栈大,那么堆栈指针

可能越界,就会造成不可预知的后果。这个结论也支持了前面的“堆栈”那篇文章的推理。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
抱歉,我无法回答涉及编程问题以外的问题。 以下是一个简单的C语言程序,实现了添加菜单和相应的函数功能: #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_NAME_LEN 20 #define MAX_STACK_SIZE 100 // 定义堆栈结构体 typedef struct Stack { char names[MAX_STACK_SIZE][MAX_NAME_LEN]; int top; } Stack; // 初始化堆栈 void initStack(Stack *s) { s->top = -1; } // 向堆栈中添加一个名称 void addOneName(Stack *s) { char name[MAX_NAME_LEN]; printf("请输入要添加的名称:"); scanf("%s", name); if (s->top == MAX_STACK_SIZE - 1) { printf("堆栈已满,无法添加!\n"); } else { strcpy(s->names[++s->top], name); printf("名称 %s 添加成功!\n", name); } } // 从堆栈中删除一个名称 void removeOneName(Stack *s) { if (s->top == -1) { printf("堆栈已空,无法删除!\n"); } else { char name[MAX_NAME_LEN]; strcpy(name, s->names[s->top--]); printf("名称 %s 删除成功!\n", name); } } // 显示堆栈中所有名称 void displayAll(Stack *s) { if (s->top == -1) { printf("堆栈已空!\n"); } else { printf("堆栈中的名称为:\n"); for (int i = s->top; i >= 0; i--) { printf("%s\n", s->names[i]); } } } int main() { Stack s; initStack(&s); int choice; do { printf("\n请选择以下选项之一:\n"); printf("1.将名称添加到堆栈\n"); printf("2.从堆栈中删除名称\n"); printf("3.显示堆栈的内容\n"); printf("4.辞去\n"); printf("请输入选项:"); scanf("%d", &choice); switch (choice) { case 1: addOneName(&s); break; case 2: removeOneName(&s); break; case 3: displayAll(&s); break; case 4: printf("谢谢使用,再见!\n"); break; default: printf("选项无效,请重新输入!\n"); } } while (choice != 4); return 0; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值