我有一个简短的hello world程序:
#include <stdio.h>
static const char* msg = "Hello world";
int main(){
printf("%s\n", msg);
return 0;
}
我使用gcc将其编译为以下汇编代码:
.file "hello_world.c"
.section .rodata
.LC0:
.string "Hello world"
.data
.align 4
.type msg, @object
.size msg, 4
msg:
.long .LC0
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
subl $16, %esp
movl msg, %eax
movl %eax, (%esp)
call puts
movl $0, %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4"
.section .note.GNU-stack,"",@progbits
我的问题是:如果我要用汇编语言编写该程序(而不是用C编写然后编译为汇编语言),此代码的所有部分是否必不可少?我了解组装说明,但是有些部分我不理解。例如,我不知道什么是.cfi
*,而且我想知道是否需要包括此文件才能在程序集中编写该程序。
可以在这个平台上正常工作的绝对最低要求是
.globl main
main:
pushl $.LC0
call puts
addl $4, %esp
xorl %eax, %eax
ret
.LC0:
.string "Hello world"
但这违反了许多ABI要求。符合ABI计划的最低要求是
.globl main
.type main, @function
main:
subl $24, %esp
pushl $.LC0
call puts
xorl %eax, %eax
addl $28, %esp
ret
.size main, .-main
.section .rodata
.LC0:
.string "Hello world"
目标文件中的其他所有内容是编译器未尽可能严格地优化代码,或者是要写入目标文件的 可选 注释。
这些.cfi_*
指令尤其是可选的注释。当且仅当函数可能在引发C ++异常时位于调用堆栈上时,才有 必要
使用它们,但是它们在您可能要从中提取堆栈跟踪信息的任何程序中都很 有用
。如果您打算用汇编语言手工编写非平凡的代码,那么值得学习如何编写它们。不幸的是,它们的文献很少。我目前找不到我认为值得链接的任何内容。
线
.section .note.GNU-stack,"",@progbits
了解您是否手工编写汇编语言也很重要;它是另一个可选的注释,但是却是一个有价值的注释,因为它的意思是“此目标文件中的任何内容都不需要堆栈是可执行的”。如果程序中的所有目标文件都具有此批注,则内核将使堆栈无法执行,从而在某种程度上提高了安全性。
(为了表明您 确实 需要堆栈是可执行的,请放置"x"
而不是""
。如果您使用其“嵌套功能”扩展名,则GCC可以这样做。(不要这样做。)
可能值得一提的是,在GCC和GNU binutils使用的“
AT&T”汇编语法(默认情况下)中,存在三种类型的行:在其上带有单个标记并以冒号结尾的行是标签。(我不记得在标签中可以显示哪些字符的规则。) 第一条
标记以点开头但 不 以冒号结尾的行是对汇编程序的某种指令。其他都是汇编指令。
我正在为64位mips机器使用gcc编译器。我注意到生成的一段汇编代码很有趣。下面是详细信息: 通常,bnez将立即跳到0xb0。但在0xb0之后的块中,我确信程序必须使用a1作为参数。但是我们可以看到,在0xb0之后,a1从未出现在块中。 但是a1在0x58中使用,就在bnez(0x54)之后。 那么0x54和0x58指令有可能同时执行吗?超标量处理器通过同时将多条指令分派到处理器上的冗余功能单
因此,通常关于通过汇编代码提高性能的问题的答案是“不要打扰,编译器比你聪明”。我明白了。 但是,我注意到优化的线性代数库(例如ACML)可以比标准编译库实现2到5倍的性能改进。例如,在我的8核机器上,与现有的单线程BLAS实现相比,优化的矩阵乘法运行速度快了30倍以上,这意味着,在考虑了由于使用所有内核而提高的8倍之后,仅仅通过优化仍然可以提高4倍。 所以在我看来,优化的汇编代码确实可以带来巨大的
问题内容: 我想知道是否可以在Swift中编写内联汇编。 我知道在Objective-C中,您可以使用如下代码: 但是在Swift中似乎无法使用 。 有谁知道如何使用,如果可能的话。我没有找到任何关于它的信息,所以我认为这是一个很好的问题。 问题答案: 要扩展Robert Levy所说的内容,您可以只使用Swift / Obj-C互操作功能,并编写一个可以处理ASM内容的Obj- C类,然后可以从
问题内容: 我想要一个简单明了的JVM汇编器。它应该采用Java虚拟机规范中描述的助记符语言编写的文本文件,并生成类文件,即字节码。 需要说明的是:我不希望有一个可以通过API调用生成类文件的库。 JVM汇编程序的当前状态是什么?他们是否支持invokedynamic(对我来说不是强制性的,而是优势)?我可以在什么操作系统上使用它们?他们各自的优缺点是什么? 问题答案: 茉莉是事实上的标准。最新版
问题内容: 有人告诉我要使用反汇编程序。是否有任何内置的?最简单的方法是什么? 问题答案: 我认为没有标志,因为它主要是编译器,但是另一个GNU开发工具可以。带有/ 标志: 反汇编如下所示:
译者:巩子惠 词嵌入是一种由真实数字组成的稠密向量,每个向量都代表了单词表里的一个单词。 在自然语言处理中,总会遇到这样的情况:特征全是单词!但是,如何在电脑上表述一个单词呢?你在电脑上存储的单词的ascii码,但是它仅仅代表单词怎么拼写,没有说明单词的内在含义(你也许能够从词缀中了解它的词性,或者从大小写中得到一些属性,但仅此而已)。 更重要的是,你能把这些ascii码字符组合成什么含义?当代表