当前位置: 首页 > 知识库问答 >
问题:

未定义的行为是否适用于ASM代码?

白子默
2023-03-14

假设您知道您的软件只会在符号溢出行为定义良好的两台互补机器上运行。签名溢出在C和C中仍然是未定义的行为,编译器可以用“ret”替换整个程序,启动核战争,格式化驱动器,或者让恶魔从你的鼻子里飞出来。

假设您在内联 asm 中进行了签名溢出,您的程序是否仍会调用 UB?

如果是,那么单独编译和链接的汇编程序呢?

共有2个答案

上官思博
2023-03-14

只要你说你在内联asm中有签名溢出,就意味着你说的是一个特殊的编译器(或一组编译器),因为在C和C中,对asm声明的支持及其含义是由编译器定义的。

如果编译器通过允许在其输出中直接包含汇编代码来定义asm关键字,并且如果机器允许有符号溢出,那么内联asm中的有符号溢出是为该编译器和该机器完美定义的:它是处理器将给出的结果。您仍然应该控制它是否会导致一个有符号整数的陷阱表示,但无论如何它已经被定义了。以UB结尾的唯一情况是当编译器说用有符号整数表示会导致未定义的行为。但是我知道没有一个是这样的,你已经在一个定义好的有限的编译器和机器的环境中了。

汇编模块和C和/或C代码的单独编译对于该编译器和机器集是相同的:结果是定义的实现与UB不同。

标准(C和C)中明确定义的实现的另一个例子是char类型是否有符号:如果你不知道你使用的编译器是什么,你不能依赖它,但是一旦你选择编译器实现,该实现就需要说它是有符号的还是无符号的,并且它不是未定义的行为,这意味着编译器不能用ret替换完整的代码。

融烨华
2023-03-14

“未定义的行为”是指 C 或 C 标准不定义程序的行为。如果您的程序包含内联程序集,那么应该很清楚,它的行为通常不会由C或C标准描述。其他一些标准甚至可能定义行为,但这仍然不意味着在C或C标准的背景下“定义行为”。

也就是说,C标准确实需要支持的扩展的文档。如果您的程序的行为可以从您的实现的文档中推断出来,并且您的实现使您的程序行为不同,那么这是您的实现未能符合标准:

4.一致性

8实现应附有定义所有实现定义和特定于语言环境的特征以及所有扩展的文档。

对于 C,这个要求被削弱了:

1.4实施合规性[合规性简介]

9每一个实现都应该包括文件,确定所有它不支持的有条件支持的结构,并定义所有特定于地区的特征。

1.9程序执行[简介执行]

2抽象机器的某些方面和操作在本国际标准中被描述为实现定义的[...]每个实现都应包括描述其在这些方面的特征和行为的文档。[...]

我无法找到要记录扩展的要求,如果记录了扩展,则无法正确记录。这表明,在C中,即使您的实现将程序的行为定义为扩展,如果事实证明文档是错误的,那也太糟糕了。

对于C半标准的< code>asm语句(如注释中所述,“< code>asm声明是有条件支持的;它的含义是实现定义的。”),如果您的实现支持它,就需要对它进行记录,但是当然,对于实现来说,以不同于C标准所暗示的方式支持内联汇编是一种常见的做法,所以这不会给您带来太多额外的好处。

 类似资料:
  • 下面是一些C代码: 我得到以下输出: a(3,5) f(9.5) ~A() 一、 因为我希望它能起作用。但我不确定在<code>f</code>返回后是否必须调用<code>A</code>的析构函数。有保证吗?返回的指针在调用,是否会以某种方式变得无效?

  • 尽管标题出现了,但这并不是一个哲学问题。 从未初始化的数组读取 使用错误数据 使用不可移植构造。(即内存分配的细节1) 导致具有的行为 标准没有要求产生可预测的效果 我会称之为“未定义的行为”。但也许我错过了什么(?) null null

  • 问题内容: var x int done := false go func() { x = f(…); done = true } while done == false { } 这是Go代码。我的恶魔告诉我,这是UB代码。为什么? 问题答案: Go Memory Model不保证该程序将始终遵守在goroutine中写入x的值。go常规销毁 部分中提供了一个类似的错误程序作为示例。 在本节中,G

  • 一位博客作者提出了关于空指针解引用的讨论: http://www.viva64.com/en/b/0306/ 我在这里提出了一些反驳意见: http://bit.ly/1L98GL4 他引用标准的主要推理是这样的: 的” C99标准说了以下关于” 一元的操作数 表达'podhd- 如果将空指针常量转换为指针类型,那么得到的指针(称为空指针)肯定不等于指向任何对象或函数的指针。 当“左值在计算时不指

  • 考虑以下C程序: null 访问易失性对象、修改对象、修改文件,或者调用执行那些操作中的任何操作的函数都是副作用,它们是执行环境状态的改变。表达式的计算通常包括值计算和副作用的启动。用于lvalue表达式的值计算包括确定指定对象的标识。 Sequenced before是单线程执行的计算之间的非对称、传递、成对关系,它导致这些计算之间的部分顺序。给定任意两个评价A和B,如果A排序在B之前,那么A的

  • 我正在将tomcat服务器从tomcat7升级到Tomcat8。但Struts1.1似乎不能在Tomcat8上工作。有人知道Tomcat8不支持Struts1.1吗。 下面是堆栈跟踪