数组与指针实验

news2024/12/24 0:29:20

指针与数组实验

先简单看一下以下c代码

#include <stdio.h>
#include <stdlib.h>
int main() {
  char array[10];
  array[0] = 0x56;
  array[1] = 0x78;
  array[9] = 0x12;
  char *p = (char *)malloc(10);
  p[0] = 0x34;
  p[1] = 0x12;
  printf("%p\n%p\n%p\n%p\n", array, &array, p, &p);
}

生成目标文件并进行反汇编

gcc point.c -o point  -g # 加上调试选项
objdump -S point > point.s -g
gcc point.c -o point -fno-stack-protector -g #关掉栈保护机制

截取主要汇编代码

0000000000001189 <main>:
#include <stdio.h>
#include <stdlib.h>
int main() {
    1189:	f3 0f 1e fa          	endbr64 
    118d:	55                   	push   %rbp
    118e:	48 89 e5             	mov    %rsp,%rbp
    1191:	48 83 ec 20          	sub    $0x20,%rsp
    1195:	64 48 8b 04 25 28 00 	mov    %fs:0x28,%rax
    119c:	00 00 
    119e:	48 89 45 f8          	mov    %rax,-0x8(%rbp)
    11a2:	31 c0                	xor    %eax,%eax
  char array[10];
  array[0] = 0x56;
    11a4:	c6 45 ee 56          	movb   $0x56,-0x12(%rbp)
  array[1] = 0x78;
    11a8:	c6 45 ef 78          	movb   $0x78,-0x11(%rbp)
  array[9] = 0x12;
    11ac:	c6 45 f7 12          	movb   $0x12,-0x9(%rbp)
  char *p = (char *)malloc(10);
    11b0:	bf 0a 00 00 00       	mov    $0xa,%edi
    11b5:	e8 d6 fe ff ff       	callq  1090 <malloc@plt>
    11ba:	48 89 45 e0          	mov    %rax,-0x20(%rbp)
  p[0] = 0x34;
    11be:	48 8b 45 e0          	mov    -0x20(%rbp),%rax
    11c2:	c6 00 34             	movb   $0x34,(%rax)
  p[1] = 0x12;
    11c5:	48 8b 45 e0          	mov    -0x20(%rbp),%rax
    11c9:	48 83 c0 01          	add    $0x1,%rax
    11cd:	c6 00 12             	movb   $0x12,(%rax)
  printf("%p\n%p\n%p\n%p\n", array, &array, p, &p);
    11d0:	48 8b 4d e0          	mov    -0x20(%rbp),%rcx
    11d4:	48 8d 75 e0          	lea    -0x20(%rbp),%rsi
    11d8:	48 8d 55 ee          	lea    -0x12(%rbp),%rdx
    11dc:	48 8d 45 ee          	lea    -0x12(%rbp),%rax
    11e0:	49 89 f0             	mov    %rsi,%r8
    11e3:	48 89 c6             	mov    %rax,%rsi
    11e6:	48 8d 3d 17 0e 00 00 	lea    0xe17(%rip),%rdi        # 2004 <_IO_stdin_used+0x4>
    11ed:	b8 00 00 00 00       	mov    $0x0,%eax
    11f2:	e8 89 fe ff ff       	callq  1080 <printf@plt>
    11f7:	b8 00 00 00 00       	mov    $0x0,%eax
    11fc:	48 8b 7d f8          	mov    -0x8(%rbp),%rdi
    1200:	64 48 33 3c 25 28 00 	xor    %fs:0x28,%rdi
    1207:	00 00 
    1209:	74 05                	je     1210 <main+0x87>
    120b:	e8 60 fe ff ff       	callq  1070 <__stack_chk_fail@plt>
    1210:	c9                   	leaveq 
    1211:	c3                   	retq   
    1212:	66 2e 0f 1f 84 00 00 	nopw   %cs:0x0(%rax,%rax,1)
    1219:	00 00 00 
    121c:	0f 1f 40 00          	nopl   0x0(%rax)

fs:0x28与linux的堆栈保护机制有关,为简化问题,将该机制关掉。
面试官不讲武德,居然让我讲讲蠕虫和金丝雀!
Why does this memory address %fs:0x28 ( fs[0x28] ) have a random value?
再次反汇编,并加上一些注释

0000000000001169 <main>:
#include <stdio.h>
#include <stdlib.h>
int main() {
    1169:	f3 0f 1e fa          	endbr64 
    116d:	55                   	push   %rbp
    116e:	48 89 e5             	mov    %rsp,%rbp
    1171:	48 83 ec 20          	sub    $0x20,%rsp   # 申请32字节堆栈空间
    # rbp-1到rbp-10为array空间,array为rbp-10地址别名,array[9]即array+9 * sizeof(char)
    # 数组赋值一步到位
  char array[10];
  array[0] = 0x56;
    1175:	c6 45 f6 56          	movb   $0x56,-0xa(%rbp) 
  array[1] = 0x78;
    1179:	c6 45 f7 78          	movb   $0x78,-0x9(%rbp)
  array[9] = 0x12;
    117d:	c6 45 ff 12          	movb   $0x12,-0x1(%rbp)
  char *p = (char *)malloc(10);     # 指针变量也是局部变量,占8个字节 rbp-17到rbp-24
    1181:	bf 0a 00 00 00       	mov    $0xa,%edi   # 申请10个字节空间
    1186:	e8 e5 fe ff ff       	callq  1070 <malloc@plt>
    118b:	48 89 45 e8          	mov    %rax,-0x18(%rbp)
  # 指针赋值需要两步/三步
  p[0] = 0x34;
    118f:	48 8b 45 e8          	mov    -0x18(%rbp),%rax # 取得指针变量中存储的地址
    1193:	c6 00 34             	movb   $0x34,(%rax)     # 将值写入该地址
  p[1] = 0x12;
    1196:	48 8b 45 e8          	mov    -0x18(%rbp),%rax # 取得指针变量中存储的地址
    119a:	48 83 c0 01          	add    $0x1,%rax        # 设置偏移量
    119e:	c6 00 12             	movb   $0x12,(%rax)     # 将值写入该地址 
    # lea: Load Effective Address,即装入有效地址的意思,它的操作数就是地址
  printf("%p\n%p\n%p\n%p\n", array, &array, p, &p);
    11a1:	48 8b 4d e8          	mov    -0x18(%rbp),%rcx # p
    11a5:	48 8d 75 e8          	lea    -0x18(%rbp),%rsi # &p
    11a9:	48 8d 55 f6          	lea    -0xa(%rbp),%rdx  # &array
    11ad:	48 8d 45 f6          	lea    -0xa(%rbp),%rax  # array
    11b1:	49 89 f0             	mov    %rsi,%r8
    11b4:	48 89 c6             	mov    %rax,%rsi
    11b7:	48 8d 3d 46 0e 00 00 	lea    0xe46(%rip),%rdi        # 2004 <_IO_stdin_used+0x4>
    11be:	b8 00 00 00 00       	mov    $0x0,%eax
    11c3:	e8 98 fe ff ff       	callq  1060 <printf@plt>
    11c8:	b8 00 00 00 00       	mov    $0x0,%eax
    11cd:	c9                   	leaveq 
    11ce:	c3                   	retq   
    11cf:	90                   	nop

在这里插入图片描述
C++内存模型以及寄存器指针rsp和rbp
看完汇编代码,可以很容易猜到:p与&p结果不一样,array与&array结果一致。

0x7ffd85499f96
0x7ffd85499f96
0x55e303c302a0
0x7ffd85499f88

使用gdb显示相关数据

可以使用examine命令(简写是x)来查看内存地址中的值。x命令的语法如下所示:

x/<n/f/u> <addr>

n:是正整数,表示需要显示的内存单元的个数,即从当前地址向后显示n个内存单元的内容,
一个内存单元的大小由第三个参数u定义。

f:表示addr指向的内存内容的输出格式,s对应输出字符串,此处需特别注意输出整型数据的格式:
  x 按十六进制格式显示变量.
  d 按十进制格式显示变量。
  u 按十进制格式显示无符号整型。
  o 按八进制格式显示变量。
  t 按二进制格式显示变量。
  a 按十六进制格式显示变量。
  c 按字符格式显示变量。
  f 按浮点数格式显示变量。

u:就是指以多少个字节作为一个内存单元-unit,默认为4。u还可以用被一些字符表示:
  如b=1 byte, h=2 bytes,w=4 bytes,g=8 bytes.

<addr>:表示内存地址。


Reading symbols from ./point...
(gdb) b point.c:11
Breakpoint 1 at 0x11a1: file point.c, line 11.
(gdb) r
Starting program: /root/tianchi/codebase/expr/point/point 

Breakpoint 1, main () at point.c:11
11        printf("%p\n%p\n%p\n%p\n", array, &array, p, &p);
(gdb) p &array
$1 = (char (*)[10]) 0x7fffffffdef6
(gdb) p &p
$2 = (char **) 0x7fffffffdee8
(gdb) p p
$3 = 0x5555555592a0 "4\022"
(gdb) x/10ab 0x5555555592a0  # 查看指针变量指向区域内容
0x5555555592a0: 0x34    0x12    0x0     0x0     0x0     0x0     0x0     0x0
0x5555555592a8: 0x0     0x0
(gdb) x/32tb 0x7fffffffdee8	 # 打印该地址之上32字节的内容,二进制
0x7fffffffdee8: 10100000        10010010        01010101        01010101        01010101        01010101        00000000        00000000
0x7fffffffdef0: 11110000        11011111        11111111        11111111        11111111        01111111        01010110        01111000
0x7fffffffdef8: 00000000        00000000        00000000        00000000        00000000        00000000        00000000        00010010
0x7fffffffdf00: 00000000        00000000        00000000        00000000        00000000        00000000        00000000        00000000
(gdb) x/32ab 0x7fffffffdee8  # 打印该地址之上32字节的内容,十六进制,有些前面有fff是符号位补全的原因(符号位为1),小端方式,低位在低地址
0x7fffffffdee8: 0xffffffffffffffa0      0xffffffffffffff92      0x55    0x55    0x55    0x55    0x0     0x0
0x7fffffffdef0: 0xfffffffffffffff0      0xffffffffffffffdf      0xffffffffffffffff      0xffffffffffffffff      0xffffffffffffffff      0x7f    0x56    0x78
0x7fffffffdef8: 0x0     0x0     0x0     0x0     0x0     0x0     0x0     0x12
0x7fffffffdf00: 0x0     0x0     0x0     0x0     0x0     0x0     0x0     0x0
(gdb) x/1tg 0x7fffffffdee8 # 打印指针变量内容 二进制
0x7fffffffdee8: 0000000000000000010101010101010101010101010101011001001010100000
(gdb) x/1ag 0x7fffffffdee8 # 打印指针变量内容 十六进制
0x7fffffffdee8: 0x5555555592a0
(gdb) 

注意区分“地址y”和“地址y的内容”之间的区别

指针数组
保存数据的地址保存数据
间接访问数据,首先取得指针的内容,把它作为地址,然后从这个地址提取数据。
如果指针有一个下标[i],就把指针的内容加上i为地址,从中提取数据
直接访问数据,a[i]只是简单地以a+i为地址取得数据
通常用于动态结果通常用于存储固定数目且数据类型相同的元素
相关的函数为malloc,free隐式分配和删除
通常指向匿名数据自身即为变量名

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/12001.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[附源码]Python计算机毕业设计 家乡旅游文化推广网站

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

【微信小程序】.js文件的代码结构与Page页面的生命周期

&#x1f3c6;今日学习目标&#xff1a;第十期——.js文件的代码结构与page页面的生命周期 &#x1f603;创作者&#xff1a;颜颜yan_ ✨个人主页&#xff1a;颜颜yan_的个人主页 ⏰预计时间&#xff1a;25分钟 &#x1f389;专栏系列&#xff1a;我的第一个微信小程序 文章目录…

尚医通 (二十二) --------- MongoDB 简介

目录一、NoSQL 简介二、什么是 MongoDB ?三、MongoDB 特点四、安装 MongoDB1. 数据库2. 文档3. 集合4. 适用场景五、MongoDB 概念解析一、NoSQL 简介 NoSQL (NoSQL Not Only SQL)&#xff0c;意即反 SQL 运动&#xff0c;指的是非关系型的数据库&#xff0c;是一项全新的数据…

使用SRM系统有哪些供应商管理优势?

SRM系统就是我们常说的供应商关系管理&#xff0c;它主要是用来改善与供应链上游供应商的关系&#xff0c;改善企业与供应商的关系的新型管理机制&#xff0c;使双方关系更加紧密&#xff0c;从而实现供应双赢。相信对SRM供应商关系管理系统有了解的朋友们并不陌生&#xff0c;…

[力扣] 剑指 Offer 第二天 - 复杂链表的复制

这里写目录标题题目来源题目描述示例示例 1示例 2示例 3示例 4题目解析算法 1代码实现执行结果复杂度分析算法 2代码实现执行结果复杂度分析总结耐心和持久胜过激烈和狂热。 题目来源 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcode…

鲁棒局部均值分解 (RLMD)(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

如何在Ubuntu 22.04使用wine安装windows版本微信

继上篇《如何在 Ubuntu 22.04 上安装 最新版本Wine》成功安装wine。使用以下命令安装&#xff1a; $ sudo dpkg --add-architecture i386 && sudo wget -qO - https://dl.winehq.org/wine-builds/winehq.key | sudo apt-key add - && sudo apt-add-repository…

从零开始学前端:json对象,对象的序列化和反序列化 --- 今天你学习了吗?(JS:Day16)

从零开始学前端&#xff1a;程序猿小白也可以完全掌握&#xff01;—今天你学习了吗&#xff1f;&#xff08;JS&#xff09; 复习&#xff1a;从零开始学前端&#xff1a;购物车和鲜花价格排序 — 今天你学习了吗&#xff1f;&#xff08;JS&#xff1a;Day15&#xff09; 文…

JVM基础

JVM简介 JVM是java虚拟机简称&#xff0c;JVM是一种用于计算设备的规范&#xff0c;它是一个虚构出来的计算机&#xff0c;是通过在实际计算机上仿真模拟各种计算机功能来实现的。也正式因为有了它&#xff0c;java才具有了跨平台特性&#xff0c;”一次编译&#xff0c;到处运…

隐私计算行业应用情况和标准化现状

开放隐私计算 2022-11-16 19:17 发表于浙江 开放隐私计算 开放隐私计算OpenMPC是国内第一个且影响力最大的隐私计算开放社区。社区秉承开放共享的精神&#xff0c;专注于隐私计算行业的研究与布道。社区致力于隐私计算技术的传播&#xff0c;愿成为中国 “隐私计算最后一公里的…

如何利用快解析实现个人私有云

个人云盘曾火爆一时&#xff0c;原因有二&#xff0c;一是国内可选择的网盘越来越少&#xff0c;自建网盘无疑是一个不错的选项&#xff0c;毕竟网盘是数据存在别人那&#xff0c;始终让人心里不安&#xff0c;如同车辆一样&#xff0c;云盘就是公交车&#xff0c;私有云盘就是…

Matlab:在文本和值之间转换datetimeduration

Matlab&#xff1a;在文本和值之间转换datetimeduration将值转换为文本datetimeduration将数组转换为字符串数组指定输出文本的格式指定输出文本的区域设置将文本转换为值datetime解释输入文本的格式将文本转换为值duration解释输入文本的格式从文件中读取日期和时间此示例演示…

面试经常问的Linux进程到底是什么呢?1W字从0到1详解进程的所有细节!

目录 1.冯诺伊曼体系 2.操作系统 3.进程 4.进程的三种状态 4.1概念 4.2Linux中不同进程状态 5.进程的优先级 6.进程的几个其它概念 7.进程的切换 8.环境变量 8.1环境变量的概念 8.2常见的环境变量 8.3和环境变量相关的命令 8.4查看环境变量的方法 8.5通过代码获取环境变量的方式…

微信小程序 webview组件内嵌H5二维码识别

结果 支持公众号二维码支持小程序码支持个人名片支持群聊不支持页面二维码 做法 点击图片触发previewImage预览&#xff0c;长按识别 <script type"text/javascript" src"https://res.wx.qq.com/open/js/jweixin-1.3.2.js"></script>wx.p…

IT部门不想每天忙“取数”,花了几百万买系统,还是这个办法有效

待过几年中小型传统企业的应该都有这个感知&#xff1a;虽然每个月都在采购新的软件系统&#xff0c;但整个公司的数字化仍旧一团糟&#xff0c;数字化转型是越搞越回去了。 这也很好解释。 传统企业业务部门繁多&#xff0c;在搞信息化阶段采购了很多业务系统&#xff0c;比…

C++ 11

文章目录1. 列表初始化1.1 列表初始化的使用格式1.1.1 内置类型1.1.2 自定义类型的列表初始化1.2 列表初始化的本质2. 变量类型的推导2.1 auto 关键字2.2 decltype类型推导3. 范围for4. final与override5. 智能指针6. 新增容器6.1 静态数组array6.2 单向链表 forward_list6.3 u…

【问卷调查发布系统的设计与实现】

系列文章目录 在当前社会&#xff0c;随着信息化的高速发展&#xff0c;收集数据的传统方法——问卷调查法也在发生改变。此问卷调查系统&#xff0c;可以帮助用户在短时间内创建收集数据的问卷&#xff0c;目的是突出高效性、绿色性以及便捷性。在设计过程中&#xff0c;分析…

web网页设计期末课程大作业:漫画网站设计——我的英雄(5页)学生个人单页面网页作业 学生网页设计成品 静态HTML网页单页制作

HTML实例网页代码, 本实例适合于初学HTML的同学。该实例里面有设置了css的样式设置&#xff0c;有div的样式格局&#xff0c;这个实例比较全面&#xff0c;有助于同学的学习,本文将介绍如何通过从头开始设计个人网站并将其转换为代码的过程来实践设计。 ⚽精彩专栏推荐&#x1…

Charles使用教程

目录预备知识1.HTTP调试代理工具原理2.Charles简介实验目的实验环境实验步骤一实验步骤二实验步骤三预备知识 1.HTTP调试代理工具原理 HTTP调试代理工具广泛应用于web程序开发、安全测试、流量分析等工作。HTTP调试代理工具工作于TCP/IP参考模型中的应用层&#xff0c;浏览器…

Docker容器的5个实用案例

Docker 是一个开源平台&#xff0c;可以轻松地为任何应用创建一个轻量级的、 可移植的、自给自足的容器。大多数 Docker 容器的核心是在虚拟化环境中运行的轻量级 Linux 服务器。 Docker Linux 容器有什么实际用例吗&#xff1f;现在让我们一探究竟。 为什么使用 Docker? D…