学习大会

我决定学习汇编语言。 这样做的主要原因是能够理解反汇编代码,也许能够编写更高效的代码部分(例如,通过c ++),做一些代码洞穴等。我看到有不同types的组装所以,为了我提到的目的,我该如何开始? 我应该学习什么样的程序集? 我想先学习一些简单的程序(例如计算器),但是目标本身就会被弄明白,所以我可以理解例如由IDA Pro所显示的代码。

我正在使用Windows(如果这有什么区别)。

编辑:所以,似乎每个人都指向MASM。 虽然我认为它具有高层次的function,对汇编代码程序员来说都是好的,但这不是我要找的。 它似乎有,如果,调用等指示stream行的反汇编(如IDA)没有显示。 所以,如果可能的话,我想听听的是任何人使用ASM来达到我所要求的目的(阅读IDA中的deassembled exe代码),而不仅仅是“一般”汇编程序员。

编辑:好的。 我已经在学习组装了。 我正在学习MASM,不使用对我无关紧要的高层次的东西。 我现在正在做的是在c ++中的__asm指令上尝试我的代码,所以我可以用比MASM更快的速度尝试一些事情。

从MASM32开始,从那里看FASM 。 但是你会喜欢MASM。

我已经做了很多次,并继续这样做。 在这种情况下,您的主要目标是阅读而不是编写汇编程序,我觉得这是适用的。

写你自己的反汇编。 不是为了制造下一个最大的反汇编,这个是严格为你。 目标是学习指令集。 无论我是在一个新的平台上学习汇编,还是记住我曾经认识的一个平台的汇编。 从只有几行代码开始,例如添加寄存器,然后在拆卸二进制输出和在input端添加越来越复杂的指令之间进行ping通:

1)学习特定处理器的指令集

2)了解如何为所述处理器编写代码组合的细微差别,以便可以在每个指令中摆动每个操作码位

3)你学习的指令集更好,大多数使用该指令的工程师为了谋生

在你的情况下,有几个问题,我通常build议首先使用ARM指令集,现在有更多的基于ARM的产品出货比其他任何(包括x86计算机)。 但是,现在使用ARM的可能性并不知道足够的汇编程序来编写启动代码或其他可以识别ARM的例程,可能会帮助您做什么。 ARM的第二个也是更重要的原因是因为指令长度是固定的大小和alignment。 拆解x86等可变长度的指令可能会成为您的第一个项目的噩梦,而这里的目标是学习指令集,不要创build一个研究项目。 第三个ARM是一个做得很好的指令集,寄存器是相同的,没有个别特殊的细微差别。

所以你将不得不找出你想要开始的处理器。 我首先build议msp430或ARM,然后ARM第一或第二,然后x86的混乱。 无论使用何种平台,任何平台都可以使用包含指令集以及操作码编码(机器语言的位和字节)的供应商免费的数据表或程序员参考手册。 为了学习编译器所做的事情,以及如何编写编译器不必费力的代码,了解一些指令集并了解每个编译器如何在每个指令集上实现相同的高级代码并进行优化设置。 你不想进入优化你的代码,只发现你已经使一个编译器/平台更好,但是对于其他所有的编译器/平台更糟糕。

噢,反汇编可变长度的指令集,而不是简单地从头开始和线性通过内存分解每四个字节的字,如同您将与ARM或每两个字节,如msp430(msp430具有可变长度的指令,但你仍然可以通过如果从中断向量表的入口点开始,则直线穿越内存)。 对于可变长度,您希望根据向量表或入门知识来find入口点,并了解处理器如何引导并按照执行顺序执行代码。 如果指令不是无条件分支,则必须完全解码每条指令,以知道使用了多less个字节,假定该指令之后的下一个字节是另一条指令。 您还必须存储所有可能的分支地址,并假定这些地址是起始字节地址以获取更多说明。 有一次,我成功地通过了二进制文件。 从入口点开始,我将该字节标记为指令的开始,然后通过内存线性地进行解码,直到达到无条件分支。 所有分支目标被标记为指令的起始地址。 我通过二进制文件多次传递,直到我没有发现新的分支目标。 如果在任何时候你发现说一个3字节的指令,但由于某种原因,你已经标记第二个字节作为一个指令的开始,你有一个问题。 如果代码是由高级编译器生成的,那么除非编译器做了一件坏事,如果代码有手工编写的汇编程序(就像说一个老的街机游戏),否则就会发生这种情况,很有可能会有条件分支永远不会发生比如r0 = 0,如果不是零,则跳转。 您可能需要手动编辑这些二进制文件才能继续。 为了您的直接目标,我认为将在x86上,我不认为你会有问题。

我推荐gcc工具,如果x86是你的目标,mingw32是在Windows上使用gcc工具的简单方法。 如果不是mingw32 plus msys是一个很好的从binutils和gcc源代码生成交叉编译器的平台(通常很容易)。 mingw32比cygwin有一些优点,比如明显更快的程序,并且避免了cygwin dll地狱。 海湾合作委员会和binutils将允许你用C编写或汇编和反汇编你的代码,并有更多的网页比你可以读取告诉你如何做任何一个或所有三个。 如果你打算使用可变长度指令集,我强烈build议你使用一个包含反汇编程序的工具集。 以x86为例的第三方反汇编器将会是一个挑战,因为你永远不知道它是否正确地反汇编。 其中的一部分依赖于操作系统,目标是将模块编译为二进制格式,其中包含标记来自数据指令的信息,以便反汇编程序可以做出更准确的工作。 这个主要目标的另一个select是有一个工具,可以直接编译到汇编器供您检查,然后希望当它编译为二进制格式时,它会创build相同的指令。

短(好吗稍短)回答你的问题。 写一个反汇编程序来学习一个指令集。 我会从RISC开始,像ARM一样学习。 一旦你知道一个指令集,通过第三个指令集,其他人可以更容易地拿起,通常在几个小时内,你可以立即使用数据手册的语法来编写代码。 所有值得使用的处理器都有一个数据表或参考手册,描述操作码的位和字节。 学习像ARM这样的RISC处理器和像x86这样的CISC足以感受到差异,例如不得不通过寄存器来处理所有事情,或者能够使用更less或者没有寄存器直接在内存上执行操作。 三个操作数指令与两个等等。当您调整高级代码时,编译多个处理器并比较输出。 您将学到的最重要的事情是,无论编写高级代码有多好,编译器的质量和所做的优化select都会对实际指令产生巨大的影响。 我推荐使用llvm和gcc(使用binutils),既不产生很好的代码,但它们是多平台和多目标的,都有优化器。 而且两者都是免费的,您可以轻松地从各种目标处理器的源代码构build交叉编译器。

从高层次上看,手工编写的程序集和编译器生成的程序集通常是非常不同的。 当然,程序里面的内容也会非常相似(毕竟,编码a = b + c只有很多不同的方法),但是当你试图对某些东西进行逆向工程时,它们并不是那么麻烦。 编译器会为简单的可执行文件添加大量的样板代码:上次我比较的时候,GCC编译的“Hello World”约为4kB,而如果用手工编写,大约有100字节。 在Windows上更糟糕:上一次我比较(当然,这是上个世纪 )最小的“Hello World”,我可以让我的Windows编译器的select生成是52kB! 通常这个样板只执行一次,所以对程序速度没有太大的影响 – 就像我上面所说的那样,程序的核心,大部分执行时间花费的部分通常是非常相似的,无论是编译还是编译手写。

在一天结束的时候,这意味着一个专家程序员和一个专家拆装者是两个不同的专业。 通常他们是在同一个人身上发现的,但是他们真的是分开的,而学习如何成为一名优秀的汇编编码人员对于学习逆向工程并无帮助。

你想要做的是从英特尔和AMD获得IA-32和AMD64(这两个都是覆盖在一起)的体系结构手册,并查看指令和操作码的早期部分。 也许在汇编语言上阅读一两个教程,只是为了了解汇编语言的基础知识。 然后抓一个你感兴趣的样本程序,并对其进行反汇编:逐步控制stream程并试图了解它在做什么。 看看你是否可以修补它来做别的事情。 然后再用另一个程序再试一次,重复,直到你足够舒适,试图达到更有用的目标。 您可能对逆向工程社区生成的“crackmes”感兴趣,这些对逆向工程感兴趣的人来说是一个挑战,希望能够在此学到一些东西。 他们从基本(从这里开始!)变得困难到不可能。

最重要的是,你只需要练习 。 和许多其他学科一样,通过逆向工程,实践使得完美…或者至less更好

我将会反驳大多数答案,并推荐Knuth的MIPS RISC架构的MMIX变体。 它不会像x86或ARM汇编语言那样具有实用性(不是说它们在现实生活中最重要的就是它们自身的重要性……–),但它将为您解开Knuth最新的魔力版本的有史以来最伟大的杰作深入低层次的algorithm和数据结构的理解 – TAOCP ,“计算机程序devise艺术”。 我引用的两个url的链接是开始探索这种可能性的好方法!

(我不了解你,但我很高兴与大会)

一个简单的工具组装实验已经安装在您的电脑。

转到开始菜单 – >运行,然后inputdebug

debugging(命令)

debug是DOS,MS-DOS,OS / 2和Microsoft Windows(只有x86版本,不是x64)运行程序debug.exe(或DEBUG.COM在旧版本的DOS)中的命令。 debugging可以作为汇编,反汇编或hex转储程序,允许用户以交互方式检查内存内容(汇编语言,hex或ASCII),进行更改,并select性地执行COM,EXE和其他文件types。 它也有几个子命令用于访问特定的磁盘扇区,I / O端口和内存地址。 MS-DOSdebugging运行在 16位进程级别,因此它被限制为16位计算机程序 。 FreeDOS Debug也有一个支持32位DPMI程序的“DEBUGX”版本。

教程:

  • debugging指南
  • PC程序如何工作:了解x86(Intel)机器代码
  • debugging教程

如果您想了解在IDA Pro (或OllyDbg )中看到的代码,则需要了解编译代码的结构。 我推荐“ 逆向:逆向工程的秘密 ”一书

当我开始学习汇编(15年前)时,我尝试了几个星期的debug
请注意, debug在基本机器级别工作,没有高级别的汇编命令。

现在一个简单的例子:

a开始编写汇编代码 – 键入下面的程序 – 最后给g来运行它。

替代文字

(如果AH寄存器设置为2 INT 21将在屏幕上显示存储在DL寄存器中的ASCII字符INT 20终止程序)

我发现黑客攻击的艺术是一个有趣的,有用的方法进入这个主题…不能说我曾经直接使用知识,但这并不是我读它的原因。 它让你更加深入地了解你的代码编译的指令,这些指令偶尔有助于理解更微妙的错误。

不要被标题推迟。 本书第一部分的大部分内容是Eric Raymond所说的“黑客”:创造性的,令人惊讶的,几乎偷偷摸摸的解决难题的方法。 我(也许你)对安全方面的兴趣不大。

我不会把重点放在编写程序,至less不是一开始。 如果你在x86上(我假设你是,因为你使用的是Windows),有很多怪异的特殊情况,这是毫无意义的学习。 例如,许多指令假设你正在一个你没有明确指定名字的寄存器上运行,而其他的指令只能在一些寄存器上工作,而不是其他指令。

我会对您理解的基础知识足够了解,然后直接跳入并尝试理解编译器的输出。 用英特尔手册武装自己,直接跳入编译器的输出。 将感兴趣的代码隔离成一个小函数,这样你就可以确定理解整个事情。

我会考虑的基础是:

  • 注册人:有多less人,他们的名字是什么,他们的大小是多less?
  • 操作数顺序: add eax, ebx表示“将ebx添加到eax并将结果存储在eax中”。
  • FPU:学习浮点堆栈的基础知识以及如何转换到fp。
  • 寻址模式:[base + offset * multiplier],但乘数只能是1,2或4(或可能是8?)
  • 调用约定:参数如何传递给函数?

很多时候,编译器会发出什么惊奇的声音。 弄清楚为什么编译器认为这将是一个好主意。 它会教你很多。

这可能也有助于用Agner Fog的手册来武装自己,尤其是列举一个手册 。 它会告诉你大概每个指令是多么昂贵,虽然这是很难直接量化现代处理器。 但是这将有助于解释为什么,例如,编译器为了避免发出一个idiv指令而idiv

我唯一的build议是,当你有select的时候,总是使用英特尔语法而不是AT&T。 我曾经在这一点上非常中立,直到我意识到两者之间的一些指令完全不同(例如,AT&T语法中的movsxd是Intel语法中的movsxd )。 由于手册都是使用英特尔语法编写的,所以请坚持。

祝你好运!

汇编语言艺术 – 玩得开心;)

哦, 在这里

我开始学习MIPS这是一个非常紧凑的32位架构。 这是一个简化的指令集,但是这使得初学者容易掌握。 您仍然可以了解assembly如何工作,而不会被复杂性所淹没。 你甚至可以下载一个漂亮的小IDE,这将允许你编译你的MIPS代码: clicky一旦你掌握了它,我认为移动到更复杂的体系结构将会容易得多。 至less这是我的想法:)在这一点上,你将有内存分配和pipe理,逻辑stream程,debugging,testing等基本知识。

build议使用debugging是一个有趣的,许多巧妙的技巧可以做到这一点。 但是,对于现代操作系统,学习16位汇编可能会稍微有用。 请考虑使用ntsd.exe。 它内置于Windows XP中(不幸的是,它在Server 2003及更高版本中被抽出),这使得它成为一个方便的工具,因为它被广泛使用。

也就是说,XP中的原始版本存在一些bug。 如果你真的想要使用它(或者cdb或者windbg,它们在命令语法和debugging后端方面基本上是不同的接口),你应该安装免费的windowsdebugging工具包。

包中包含的debugger.chm文件在试图找出不寻常的语法时特别有用。

关于ntsd的好处是你可以在任何你靠近的XP机器上popup它,并用它来assembly或反汇编。 它使一个/很棒/ X86大会学习工具。 例如(使用cdb,因为它在dos提示符中是内联的,否则它是相同的):

(符号错误,因为他们是不相关的跳过 – 也希望这种格式的工作,这是我的第一篇文章)

 C:\Documents and Settings\User>cdb calc Microsoft (R) Windows Debugger Version 6.10.0003.233 X86 Copyright (c) Microsoft Corporation. All rights reserved. CommandLine: calc Symbol search path is: *** Invalid *** Executable search path is: ModLoad: 01000000 0101f000 calc.exe ModLoad: 7c900000 7c9b2000 ntdll.dll ModLoad: 7c800000 7c8f6000 C:\WINDOWS\system32\kernel32.dll ModLoad: 7c9c0000 7d1d7000 C:\WINDOWS\system32\SHELL32.dll ModLoad: 77dd0000 77e6b000 C:\WINDOWS\system32\ADVAPI32.dll ModLoad: 77e70000 77f02000 C:\WINDOWS\system32\RPCRT4.dll ModLoad: 77fe0000 77ff1000 C:\WINDOWS\system32\Secur32.dll ModLoad: 77f10000 77f59000 C:\WINDOWS\system32\GDI32.dll ModLoad: 7e410000 7e4a1000 C:\WINDOWS\system32\USER32.dll ModLoad: 77c10000 77c68000 C:\WINDOWS\system32\msvcrt.dll ModLoad: 77f60000 77fd6000 C:\WINDOWS\system32\SHLWAPI.dll (f2c.208): Break instruction exception - code 80000003 (first chance) eax=001a1eb4 ebx=7ffd6000 ecx=00000007 edx=00000080 esi=001a1f48 edi=001a1eb4 eip=7c90120e esp=0007fb20 ebp=0007fc94 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202 ntdll!DbgBreakPoint: 7c90120e cc int 3 0:000> r eax eax=001a1eb4 0:000> r eax=0 0:000> a eip 7c90120e add eax,0x100 7c901213 0:000> u eip ntdll!DbgBreakPoint: 7c90120e 0500010000 add eax,100h 7c901213 c3 ret 7c901214 8bff mov edi,edi 7c901216 8b442404 mov eax,dword ptr [esp+4] 7c90121a cc int 3 7c90121b c20400 ret 4 ntdll!NtCurrentTeb: 7c90121e 64a118000000 mov eax,dword ptr fs:[00000018h] 7c901224 c3 ret 0:000> t eax=00000100 ebx=7ffd6000 ecx=00000007 edx=00000080 esi=001a1f48 edi=001a1eb4 eip=7c901213 esp=0007fb20 ebp=0007fc94 iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206 ntdll!DbgUserBreakPoint+0x1: 7c901213 c3 ret 0:000>` 

另外 – 当你在玩IDA的时候,一定要查看Chris Eagle的IDA Pro Book(由于StackOverflow不想让我发布两个以上的链接)。 这是最好的参考。

我想你想要学习由反汇编器输出的ASCII码化的操作码助记符(及其参数),这些操作码可以被汇编程序理解(可以用作input)。

任何汇编程序(如MASM)都可以。

和/或你可能会更好地阅读一本关于它的书(这里有推荐的书,我不记得是哪一本书)。

你在做Windows的其他开发工作吗? 在哪个IDE上? 如果是VS,那么不需要额外的IDE来阅读反汇编的代码:debugging你的应用程序(或附加到外部应用程序),然后打开反汇编窗口 (默认设置,这是Alt + 8)。 按照通过普通代码的步骤来观看内存/寄存器。 您可能还想保持一个注册窗口打开(默认为Alt + 5)。

英特尔提供了免费的手册 ,既提供了基本架构(寄存器,处理器单元等)的调查,也提供了完整的指令参考。 随着架构的成熟和越来越复杂,“基础架构”手册的可读性越来越差。 如果你可以使用旧版本,那么你可能会有一个更好的开始(甚至是P3手册 – 他们更好地解释了相同的基本执行环境)。

如果你在乎一本书的投资, 这是一个很好的介绍性文字。 search“x86”的亚马逊,你会得到很多人。 你可以从这里的另一个问题得到其他几个方向。

最后,你可以从阅读 一些 低级博客中受益颇多。 这些字节大小的信息位对我个人而言是最适合的。

这不一定能帮助你编写高效的代码!

i86操作代码或多或less是一种“传统”格式,由于Windows和Linux的大量代码和可执行二进制文件,这种格式依然存在。

它有点像拉丁文的老学者,像伽利略这样的意大利人可以用拉丁文写,他的文章可以被哥白尼这样的波兰人所理解。 尽pipe尼特拉斯特别擅长拉丁语,但这仍然是最有效的沟通方式,拉丁语是expressionmath思想的垃圾语言。

因此,编译器默认生成x86代码,现代芯片读取anceint操作代码,并将它们看到的并行risc指令与重新sorting的执行,推测性执行,stream水线等进行转换。再加上它们充分利用32位或64位寄存器实际上有(而不是你在x86指令中看到的可怜的8)。

现在所有的优化编译器都知道这是真正发生的事情,所以他们对OP代码序列进行编码,他们知道芯片可以有效地进行优化 – 即使这些序列中的某些序列看起来对于1990年代程序员来说效率不高。

在某些时候,你需要接受的是编译器作者所花费的数十年努力的成果已经得到了回报,并相信它们。

获得更高效的运行时间的最简单和最简单的方法是购买英特尔C / C ++编译器。 他们有一个利基编译器的利基市场,他们的优势是能够向芯片devise师询问里面发生了什么。

要做你想做的事情,我只是拿了英特尔指令集参考 (可能不是我使用的确切的那个,但看起来足够了)以及一些我在Visual Studio中编写的简单程序,并开始把它们扔到IDAPro / Windbg中。 当我发展自己的程序时,在crackmes的软件是有帮助的。

我假设你对Windows程序的执行有一些基本的了解。 但实际上,对于阅读汇编来说,只有几条指令要学习,并且有几条指令(例如,有一个跳转指令,跳转有几个类似jump-if-equal,jump-if-ecx-is-zero等等)。 一旦你学习了基本的指令,获得程序执行的要点非常简单。 IDA的图表视图可以帮助您,如果您使用Windbg来追踪程序,那么在您不确定的情况下弄清楚指令的操作非常简单。

经过一番这样的玩,我买了Hacker Disassembly Uncovered 。 一般来说,我在标题中远离那些带有“黑客”一词的书,但我真的很喜欢这篇文章如何深入了解编译代码如何被拆解。 他还进入编译器优化和一些有趣的效率的东西。

这一切都取决于你想了解程序的深度。 如果您正在对目标进行逆向工程以寻找漏洞,如果您正在编写漏洞利用代码或分析打包的恶意软件以获取function,则需要更多的时间才能真正实现目标(尤其是对于更高级的恶意软件)。 另一方面,如果你只是想在你最喜欢的video游戏中改变angular色的等级,那么你应该在相对较短的时间内完成任务。

我最近参加了一个电脑系统课。 议题之一是作为与硬件沟通的工具。

对我来说,如果不了解计算机系统的工作细节,组装知识就不会完整。 了解到这一点,对于为什么在一个处理器架构上的汇编指令是好的,但在另一个架构上又是糟糕的,会带来新的理解。

鉴于此,我倾向于推荐我的class级课本:

计算机系统:程序员的观点 。

计算机系统:程序员的观点http://csapp.cs.cmu.edu/public/csappcover-medium.jpg

它涵盖了x86汇编,但是这本书比这个更广泛。 它包括处理器pipe道和内存作为caching,虚拟内存系统等等。 所有这些都可以影响如何针对给定特征来优化assembly。

其中一种标准的教学assembly语言是MIPS。 你可以得到MIPS模拟器(spim)和各种教材。

就我个人而言,我不是粉丝。 我很喜欢IA32。

我个人最喜欢的是NASM,主要是因为它是多平台的,它编译MMX,SSE,64位…

我开始使用gcc编译一些简单的C源文件,并将汇编指令从gcc格式“转码”为NASM格式。 然后,您可以更改小部分代码,并validation其带来的性能改进。

NASM的文档是非常完整的,我从来不需要从书本或其他来源search信息。

一些链接,你可能会发现有用的学习汇编 – 源代码映射 –

大会和debugging的艺术

debugging – 在运行时修改代码

希望你find这些有用的。

很多好的答案在这里。 低级编程,汇编等在安全社区中很受欢迎,因此,一旦你开始,值得寻找提示和技巧。 他们甚至在x86汇编上有这样一个很好的教程 。

要真正实现你的目标,你可以考虑从你所在的IDE入手。通常是反汇编窗口,所以你可以通过代码单步执行。 通常有一种让你看到寄存器并查看内存区域的观点。

未经优化的c / c ++代码的检查将帮助build立一个链接到编译器为你的源代码生成的那种代码。 一些编译器有一些ASM保留字,可以让你在代码中插入机器指令。

我的build议是在一段时间内使用这些工具,弄湿你的脚,然后加紧? 下? 直接编译你正在运行的平台上的代码。

那里有很多很棒的工具,但是你可能会发现它更有趣,首先要避免陡峭的学习曲线。

我们学习了一个微控制器开发套件(摩托罗拉HC12)和厚数据表的汇编。

closures主题我知道,但既然你是一个Windows程序员,我不禁认为这可能是一个更适合和/或更好地利用你的时间来学习MSIL。 不,这不是汇编,但它可能在这个.NET时代更相关。

了解程序集对于debugging是有用的,但是我不会为使用它来优化代码而感到兴奋。 现代编译器现在通常在优化人类方面要好得多。

你可以看看xorpd x86 Assemblyvideo课程 。 (我写的)。 课程本身是有偿的,但练习是开源的,在github上。 如果你有一些编程经验,我认为你应该能够只是练习和理解一切。

请注意,该代码是针对Windows平台的,并且是使用Fasm汇编器编写的。 课程和练习不包含任何高级构造,但是如果您希望这样做,则可以使用Fasm创build非常复杂的macros。