Linux Gnu汇编程序。数据节值在系统调用后损坏

Linux Gnu汇编程序。数据节值在系统调用后损坏,linux,assembly,x86,gnu-assembler,Linux,Assembly,X86,Gnu Assembler,我有以下代码 .data result: .byte 1 .lcomm input 1 .lcomm cha 2 .text (some other code, syscalls) 起初一切都很好。当调用系统调用(如read)时,标签“result”处的值更改为某个随机垃圾值 有人知道怎么了吗 p.S.环境 Debian x86_64最新版本 在virtualbox中运行 使用as-gld-emacs制作最新版本 -----编辑----- “输入”的值已正确更改,但“结果”的值在更改后也更改

我有以下代码

.data
result: .byte 1
.lcomm input 1
.lcomm cha 2

.text
(some other code, syscalls)
起初一切都很好。当调用系统调用(如read)时,标签“result”处的值更改为某个随机垃圾值

有人知道怎么了吗

p.S.环境 Debian x86_64最新版本 在virtualbox中运行 使用as-gld-emacs制作最新版本

-----编辑-----

“输入”的值已正确更改,但“结果”的值在更改后也更改为随机值

int $0x80 

您看到的是从
结果
开始的4个字节,其中包括
输入
作为第2或第3个字节。(这就是为什么该值会增加256或65536的倍数,如果
print(char)result
,则保留低位字节=1)。如果您使用
p/x
以十六进制打印,这将更加明显

当没有调试信息时,
print result
的GDB默认行为是假定
int
。现在,由于这样的用户错误,在Arch Linux上使用
gdb
8.1时,
print result
表示
'result'的类型未知;将其强制转换为声明的类型

GAS+
ld
出人意料地(对我来说)将BSS和数据段合并到一个页面中,因此即使您将变量放在不同的部分中,您也会期望得到不同的处理,但它们是相邻的。(BSS由匿名零页支持,数据由文件的私有读写映射支持)

使用
gcc-nostlib-no pie test.S构建之后,我得到:

(gdb) p &result
$1 = (<data variable, no debug info> *) 0x600126
(gdb) p &input
$2 = (<data variable, no debug info> *) 0x600128 <input>
因此,是的,
.data
.bss
部分最终位于同一个ELF段中

我认为这里发生的事情是ELF元数据表示从virt addr
0x600126
开始映射
0xd8e1a
字节(零页)的MemSize。并将文件中偏移量
0x126
中的1个字节加载到虚拟地址
0x600126

因此,ELF程序加载器必须将数据从文件复制到支持BSS和
.data
部分的另一个归零页面,而不仅仅是一个mmap


它可能是一个较大的
.data
部分,链接器需要它来决定使用单独的段。

您能做一个比较吗?您没有显示实际的代码,因此很难真正了解问题所在
sys\u read
只会将字节从
buf
修改为
buf+length
。或者更好的方法是,在被修改的内存上设置一个断点,以找出修改的位置。顺便问一下,为什么要显示BSS静态数据(
.lcomm
)?是否也在修改?
int$0x80
不是执行64位系统调用的正确方法。有关详细信息,请参阅。这可能是您的问题的根源,但很难说没有一个代码段不是。也就是说,您的代码片段缺少“完整”和“可验证”的部分,这对其他人重现和诊断您的问题很重要。
打印结果
是否将
结果
视为
int
类型,即显示4个字节而不是1个字节?(尝试以十六进制输出,并检查低8位(最后两个十六进制数字)=这些应该是结果字节值)(以十六进制打印:
p/x result
@Ped7g:这里不涉及编译器本身,只涉及汇编程序+链接器,它们通常只遵循简单规则,不寻求优化(除分支位移外,尽可能使用
jmp rel8
短编码,以及最小尺寸立即和位移。)@空格:我错了,它没有在文件中存储文字零。使用
readelf
输出进一步更新了包含
.data
.bss
部分的段的工作方式。我认为变量最终会出现在
.data
部分,因为在声明t之前OP没有更改为
.bss
部分哼哼。GNU汇编程序不会将变量放入
.bss
中,除非您明确告诉它。@fuz:
.lcomm
在bss中保留空间,并且不关心当前部分。我在
.text
mov%al,cha(%rip)之后使用它进行了双重检查
不会分离故障,但
.text
中的
.byte
存储区会分离故障。使用
nm-n a.out
检查符号地址,其中包括
\u bss\u start
\u edata
,这样您就可以知道哪个静态存储在哪里。
(gdb) p &result
$1 = (<data variable, no debug info> *) 0x600126
(gdb) p &input
$2 = (<data variable, no debug info> *) 0x600128 <input>
...
Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x0000000000000126 0x0000000000000126  R E    0x200000
  LOAD           0x0000000000000126 0x0000000000600126 0x0000000000600126
                 0x0000000000000001 0x00000000000d8e1a  RW     0x200000
  NOTE           0x00000000000000e8 0x00000000004000e8 0x00000000004000e8
                 0x0000000000000024 0x0000000000000024  R      0x4

 Section to Segment mapping:
  Segment Sections...
   00     .note.gnu.build-id .text 
   01     .data .bss 
   02     .note.gnu.build-id 

...