C中的简单的基于堆栈的机器

Posted

技术标签:

【中文标题】C中的简单的基于堆栈的机器【英文标题】:simple stack-based machine in C 【发布时间】:2013-09-27 23:44:48 【问题描述】:

我必须创建一个简单的基于堆栈的机器。指令集由5条指令组成;推,弹出,添加,多,结束。我接受包含指令部分 (.text) 和数据部分 (.data) 的源代码文件,然后我必须通过模拟使用 32 位地址的内存系统将它们存储在内存中。

我必须存储在内存中的示例源代码文件可能是

    .text
main:
    push X
    push Y
    add   //remove top two words in stack and add them then put result on top of stack
    pop (some memory address)  // stores result in the address
    end

    .data
X:  3    // allocate memory store the number 3
Y:  5

关于如何做内存系统有什么建议吗?我可能应该将数据存储在一个部分(可能是一个数组?),然后在另一个部分中存储指令,但我不能只使用数组索引,因为我需要在我的代码中使用 32 位地址。

编辑:一旦我将数字 3 和 5 分配给内存中的空间(在我的数据数组中),还有没有办法用实际地址替换 X 和 Y? . . .有点像两遍汇编器可能会这样做。

【问题讨论】:

如果您听从我的建议,请从push 函数返回“地址”(即 s->top):即声明为 word push(stackp s, word w); 【参考方案1】:

数组有什么问题?如果您知道所需的尺寸,它们应该可以工作。 机器代码中的地址实际上是数组中的索引。

对数组使用 32 位索引不是问题。当然,并非所有索引都是有效的——只有从 0 到数组大小的索引。但是你需要模拟4GB的内存,还是可以设置内存大小的限制?

【讨论】:

我可以有一个限制。 . .嗯,好的,我会尝试以某种方式解决这个问题。【参考方案2】:

只是为了添加到 ugoren 的答案(有点 OT),我认为一个相对有趣的方法可能是使用 .stack 部分扩展您的规范空间,默认情况下初始化为空(就像在您的示例中一样)。

这可用于描述计算的预期中间阶段(在某个点保存/恢复实际状态)。

为了实现,我会使用非常简单的代码,比如

文件stack.h:

#ifndef STACK
#define STACK

#include <stdio.h>

/* here should be implemented the constraint about 32 bits words... */
typedef int word;

typedef struct  int top; word* mem; int allocated;  stack;
typedef stack* stackp;

stackp new_stack();
void free_stack(stackp);

void push(stackp s, word w);
word pop(stackp p);

/* extension */
stackp read(FILE*);
void write(stackp, FILE*);

#endif

文件 stack.c:

/* example implementation, use - arbitrary - chunks of 2^N */

#include <stdlib.h>
#include "stack.h"

/* blocks are 256 words */
#define N (1 << 8)

stackp new_stack() 
  stackp s = calloc(1, sizeof(stack));
  s->mem = malloc((s->allocated = N) * sizeof(word));
  return s;

void free_stack(stackp s) 
  free(s->mem);
  free(s);


void push(stackp s, int w) 
  if (s->top == s->allocated) 
     s->allocated += N;
     s->mem = realloc(s->mem, s->allocated * sizeof(word));
  
  s->mem[s->top++] = w;

word pop(stackp s) 
  if (s->top == 0)  /* exception */ 
  return s->mem[--(s->top)];

文件 main.c:

#include "stack.h"
int main() 

  stackp s = new_stack();
  word X = 3;
  word Y = 5;

  push(s, X);
  push(s, Y);
  word Z = pop(s) + pop(s);

  printf("Z=%d\n", Z);

  free_stack(s);

文件生成文件:

main: main.c stack.c

构建:

make

测试:

./main
Z=8

值得注意的是 WRT ugoren 的回答:我强调 数据隐藏,这是实现的一个有价值的部分,将有关实际功能的详细信息保存在单独的文件中。在那里我们可以添加许多细节,例如关于最大堆栈大小(实际上没有在那里强制执行)、错误处理等......

编辑:获取推送词的“地址”

word push(stackp s, int w) 
  if (s->top == s->allocated) 
     s->allocated += N;
     s->mem = realloc(s->mem, s->allocated * sizeof(word));
  
  s->mem[s->top] = w;
  return s->top++;

【讨论】:

【参考方案3】:

内存系统的关键是限制内存的范围。在操作系统中,您只能访问内存的几个部分。

因此,在您的特定程序中,您可以说,有效程序可以包含从 0x00004000 开始的地址,并且您的机器可用的内存例如是 4 MB。

然后在您的程序中创建大小为 4MB 的虚拟内存空间并存储它的开头。

下面是一个例子;请记住,这是一个示例,您必须相应地调整参数。

virtual memory start - 0x00006000 (get from malloc, or static initialization. or whatever)
stack machine memory start - 0x00004000
offset - 0x2000 (to align addresses in you OS and in your stack machine, you have to add 0x2000 to the stack machine address to get pointer to your array (in reality the offset can be negative).

如果您确实需要数组索引,只需从指针中减去虚拟内存的开头即可。

【讨论】:

以上是关于C中的简单的基于堆栈的机器的主要内容,如果未能解决你的问题,请参考以下文章

c_cpp C ++标准库中的堆栈和队列的简单示例

使用基于堆栈计算机的语言添加嵌套函数支持

在调用堆栈上很好的 C/C++ 中的事件循环实现

静态成员存储在内存中的啥位置? C#.Net中的堆栈/堆[重复]

您将如何确定系统中的堆栈是向上还是向下增长? [复制]

了解 C 中的堆栈溢出处理