鱼C论坛

 找回密码
 立即注册
查看: 993|回复: 5

[已解决]如何用c语言体现进程地址空间

[复制链接]
发表于 2020-9-18 05:31:36 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
进程地址空间是操作系统为一个特定进程创建的一组可访问地址。众所周知,进程地址空间由文本/代码段,数据(已初始化和未初始化)段,堆栈和堆组成。在此作业中,要求您使用C语言编写程序,以探索如何将进程地址空间映射到内存中。

特别是,您的代码应至少有两个文件(.c)才能将多个目标文件合并为一个可执行目标文件,并且必须存在交叉引用。例如,文件1调用文件2中定义的函数。

在您的代码中,您应该想出一种方法来显示所有不同段的位置(如上所述),即起始/结束地址或位于指定段中的变量的地址。

在您的实现中回答以下问题:a)一个堆栈帧的大小是多少? b)代码段的起始地址是什么? c)您代码中每个函数的地址是什么? d)初始化的全局变量和未初始化的变量的地址是什么?

小白在线等求助 感谢大佬!!!!
最佳答案
2020-9-18 10:26:28
本代码只适用于win32系统
#include <stdio.h>
#include <windows.h>
//已初始化全局变量
long g_Init_v = 1000;
//未初始化全局变量
long g_Uninit_v;

void fun1()
{
        long a = 100;
        long b = 200;
        long c = a + b;
}

//获取一个函数的堆栈帧
// C 函数调用参数传递,先传a,再传b,最后传返回地址
// PASCAL 函数调用参数传递,先传b,再传a,最后传返回地址
long stackframe(long a,long b)
{        
        //取参数a的地址
        long address_a = (long)(&a);
        //取参数b的地址
        long address_b = (long)(&b);
        //以高地址为堆栈帧的起始地址
        long stackBegin = address_a > address_b ? address_a : address_b;

        
        //最后定义的变量为堆栈帧的结束地址
        //堆栈帧大小 = 起始地址 - 结束地址 (因为栈是从高地址向低地址走)
        long stackframesize = stackBegin - (long)(&stackframesize);
        return stackframesize;
}

int main()
{
        //仅试用于win32系统
        //获取系统系统,主要是获取内存页面大小
        //win32的内存页面大小通常为4k,即4096字节
        SYSTEM_INFO si = {0};
        GetSystemInfo(&si);
        
        //获取主函数地址,C程序中主函数为进程入口
        long address_of_main = (long)main;
        //或取一个函数fun1的地址
        long address_of_fun1 = (long)fun1;
        
        //获取代码段地址,取值最小的函数地址为代码起始地址并按页面大小对齐
        long address_of_code = (address_of_main < address_of_fun1 ? address_of_main : address_of_fun1) / si.dwPageSize * si.dwPageSize;
        //获取已初始化全局变量地址
        long address_of_InitV = (long)(&g_Init_v);
        //已初始化全局变量地址按页面大小对齐
        long address_of_data1 = address_of_InitV / si.dwPageSize * si.dwPageSize;
        //获取未初始化全局变量地址
        long address_of_UninitV = (long)(&g_Uninit_v);
        //未初始化全局变量地址按页面大小对齐
        long address_of_data2 = address_of_UninitV / si.dwPageSize * si.dwPageSize;
        //获得一个函数的堆栈帧大小
        long stackframesize = stackframe(0,0);
        
        return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2020-9-18 05:33:20 | 显示全部楼层
用c语言写代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-9-18 10:26:28 | 显示全部楼层    本楼为最佳答案   
本代码只适用于win32系统
#include <stdio.h>
#include <windows.h>
//已初始化全局变量
long g_Init_v = 1000;
//未初始化全局变量
long g_Uninit_v;

void fun1()
{
        long a = 100;
        long b = 200;
        long c = a + b;
}

//获取一个函数的堆栈帧
// C 函数调用参数传递,先传a,再传b,最后传返回地址
// PASCAL 函数调用参数传递,先传b,再传a,最后传返回地址
long stackframe(long a,long b)
{        
        //取参数a的地址
        long address_a = (long)(&a);
        //取参数b的地址
        long address_b = (long)(&b);
        //以高地址为堆栈帧的起始地址
        long stackBegin = address_a > address_b ? address_a : address_b;

        
        //最后定义的变量为堆栈帧的结束地址
        //堆栈帧大小 = 起始地址 - 结束地址 (因为栈是从高地址向低地址走)
        long stackframesize = stackBegin - (long)(&stackframesize);
        return stackframesize;
}

int main()
{
        //仅试用于win32系统
        //获取系统系统,主要是获取内存页面大小
        //win32的内存页面大小通常为4k,即4096字节
        SYSTEM_INFO si = {0};
        GetSystemInfo(&si);
        
        //获取主函数地址,C程序中主函数为进程入口
        long address_of_main = (long)main;
        //或取一个函数fun1的地址
        long address_of_fun1 = (long)fun1;
        
        //获取代码段地址,取值最小的函数地址为代码起始地址并按页面大小对齐
        long address_of_code = (address_of_main < address_of_fun1 ? address_of_main : address_of_fun1) / si.dwPageSize * si.dwPageSize;
        //获取已初始化全局变量地址
        long address_of_InitV = (long)(&g_Init_v);
        //已初始化全局变量地址按页面大小对齐
        long address_of_data1 = address_of_InitV / si.dwPageSize * si.dwPageSize;
        //获取未初始化全局变量地址
        long address_of_UninitV = (long)(&g_Uninit_v);
        //未初始化全局变量地址按页面大小对齐
        long address_of_data2 = address_of_UninitV / si.dwPageSize * si.dwPageSize;
        //获得一个函数的堆栈帧大小
        long stackframesize = stackframe(0,0);
        
        return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-9-18 11:49:18 | 显示全部楼层
xieglt 发表于 2020-9-18 10:26
本代码只适用于win32系统

为什么都用long, 用int可以吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-9-18 11:53:30 | 显示全部楼层
zsyyf 发表于 2020-9-18 11:49
为什么都用long, 用int可以吗?

win32系统,int 和 long 是一样的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-9-18 12:07:35 | 显示全部楼层
xieglt 发表于 2020-9-18 11:53
win32系统,int 和 long 是一样的

感谢大佬
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-1-13 03:08

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表