IdiotSky


  • Home

  • Categories

  • About

  • Archives

  • Tags

  • Books

  • Search

Java8内存模型—永久代(PermGen)和元空间(Metaspace)

Posted on 26 Jul 16 | In java

JVM 内存模型

根据 JVM 规范,JVM 内存共分为虚拟机栈、堆、方法区、程序计数器、本地方法栈五个部分。

Read more »

从字节码层面看“HelloWorld”

Posted on 23 Jul 16 | In java

HelloWorld 字节码生成

众所周知,Java 程序是在 JVM 上运行的,不过 JVM 运行的其实不是 Java 语言本身,而是 Java 程序编译成的字节码文件。可能一开始 JVM 是为 Java 语言服务的,不过随着编译技术和 JVM 自身的不断发展和成熟,JVM 已经不仅仅只运行 Java 程序。任何能编译成为符合 JVM 字节码规范的语言都可以在 JVM 上运行,比较常见的 Scala、Groove、JRuby等。今天,我就从大家最熟悉的程序“HelloWorld”程序入手,分析整个 Class 文件的结构。虽然这个程序比较简单,但是基本上包含了字节码规范中的所有内容,因此即使以后要分析更复杂的程序,那也只是“量”上的变化,本质上没有区别。

Read more »

我的汇编学习之路(8)

Posted on 19 May 16 | In 汇编

这是系列的第八篇(译者注:最终篇),接下来讲讲怎么在汇编使用非整型(浮点数)。
我们有一些方法可以处理浮点数据:

  • fpu
  • sse

首先让我们看看如何将浮点数存储在内存中。有三种浮点数据类型:

  • 单精度
  • 双精度
  • 双倍扩展精度

正如英特尔的64-ia-32架构软件开发者-vol-1手册所述:

The data formats for these data types correspond directly to formats specified in the IEEE Standard 754 for Binary Floating-Point Arithmetic.

内存中呈现的单精度浮点浮点数据:

  • 符号 - 1位
  • 指数 - 8位
  • 尾数 - 23位
Read more »

我的汇编学习之路(7)

Posted on 18 May 16 | In 汇编

这是系列的第七篇,接下来要讲一下如何在c中使用汇编。
其实我们有三种方法:

  • 从C代码调用汇编例程
  • 从汇编代码调用c例程
  • 在C代码中使用内联汇编

我们来编写3个简单的Hello World程序,向我们展示如何使用assembly和C在一起。

Read more »

我的汇编学习之路(6)

Posted on 17 May 16 | In 汇编

这是系列的第六篇,接下来要讲一下AT&T汇编语法。之前一直都是用nasm汇编,但是还有其他不同语法的汇编,如fasm,yasm等等。正如我上面写的,我们要看一下gas(GNU汇编)和讲一下与nasm的不同。GCC用的是GNU汇编,所以你会看到一个简单的hello world的汇编输出:

1
2
3
4
5
6
#include <unistd.h>

int main(void) {
write(1, "Hello World\n", 15);
return 0;
}

汇编输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
	.file	"test.c"
.section .rodata
.LC0:
.string "Hello World\n"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $15, %edx
movl $.LC0, %esi
movl $1, %edi
call write
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 4.9.1-16ubuntu6) 4.9.1"
.section .note.GNU-stack,"",@progbits

看上去跟nasm汇编不同吧,让我们看看他们的不同吧。

Read more »

我的汇编学习之路(5)

Posted on 16 May 16 | In 汇编

这是关于x86_64汇编的第五章,这一章主要说宏。

宏

NASM支持两种形式的宏:

  • 单行
  • 多行

所有单行宏必须从%define指令开始。格式如下:

1
%define macro_name(parameter) value

Nasm宏的行为和外观与C类似。例如,我们可以创建以下单行宏:

1
2
%define argc rsp + 8
%define cliArg1 rsp + 24

Read more »

我的汇编学习之路(4)

Posted on 15 May 16 | In 汇编

前段时间,我开始为x86_64编写有关汇编编程的一系列博文。你可以通过asm标签找到它。不幸的是,我上次很忙,没有新帖,所以今天我继续写关于汇编的帖子,并且每周都会尝试这样做。

今天我们将看一下字符串和一些字符串操作。我们还是使用nasm汇编器和linux x86_64。

反转字符串

当然,当我们谈论汇编编程语言时,我们不能谈论字符串数据类型,实际上我们正在处理字节数组。我们尝试写简单的例子,我们将定义字符串数据,并尝试反转并将结果写入stdout。当我们开始学习新的编程语言时,这个任务似乎很简单和受欢迎。我们来看看实现。

首先,我定义初始化的数据。它将被放置在数据部分(您可以部分阅读有关章节):

1
2
3
4
5
6
7
8
section .data
SYS_WRITE equ 1
STD_OUT equ 1
SYS_EXIT equ 60
EXIT_CODE equ 0

NEW_LINE db 0xa
INPUT db "Hello world!"

Read more »

我的汇编学习之路(3)

Posted on 14 May 16 | In 汇编

栈是在内存中是一个特殊的区域,它的主要操作是lifo(后进先出)

我们有16个通用的寄存器,用来存储临时数据。它们分别是RAX, RBX, RCX, RDX, RDI, RSI, RBP, RSP 和 R8-R15。对于真实的应用程序来说,这16个寄存器太少了,所以我们用栈存储数据。另外,栈还有其他用法:当你调用一个函数,函数的返回地址拷贝到栈。当函数执行完后,地址从栈拷贝到命令计数器(RIP),应用程序就可以从函数调用的下个位置继续执行。
举个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
global _start

section .text

_start:
mov rax, 1
call incRax
cmp rax, 2
jne exit
;;
;; Do something
;;

incRax:
inc rax
ret

Read more »

我的汇编学习之路(2)

Posted on 13 May 16 | In 汇编

对于不折不扣的汇编新手来说,第一部分中出现的很多概念可能不是很明白,于是我决定写更多有价值的文章。所以,让我们开始《我的汇编学习之路》的第二部分的学习。

术语和概念

当我写了第一篇之后,我从不同的读者那获得很多反馈,第一篇中有些部分不明白,这就是本文以及接下来几篇从一些术语的描述开始的原因。

寄存器(Register):寄存器是处理器内小容量的存储结构,处理器的主要功能是数据处理,处理器可以从内存中获得数据,但这是一种低速的操作,这就是为什么处理器为什么要有自己数据存储结构,称为“寄存器”。

L小端(Little-endian):我们可以假设内存是一个大的数组,它包含一个字节一个字节的数。每个地址存储了内存“数组”中的一个元素,每个元素一个字节。举例来说,我们有 4 字节数:AA 56 AB FF,在小端模式下最低位存放在低地址上:

1
2
3
4
0 FF
1 AB
2 56
3 AA

这里,0、1、2、3 是内存地址。

大端(Big-endian):大端存储数据与小端相反。所有上面的字节序在大端模式下是:

1
2
3
4
0 AA
1 56
2 AB
3 FF

系统调用(Syscall):系统调用是用户程序要求操作系统为其完成某些工作的一种方式。你可以在这里找到系统调用表。

栈(Stack):处理器中寄存器的个数非常有限。所以栈是一块连续的内存空间,可以通过特殊寄存器如 RSP、SS、RIP 等来寻址。在接下来的文章我会专门深入介绍栈。

Read more »

我的汇编学习之路(1)

Posted on 12 May 16 | In 汇编

引言

我们很多人是开发者,每天写大量的代码,有时也不是糟糕的代码。每个人都能很轻松写下这样的代码:

1
2
3
4
5
6
7
8
#include <stdio.h>

int main() {
int x = 10;
int y = 100;
printf("x + y = %d", x + y);
return 0;
}

大家都能理解上面这段 C 语言代码完成的功能,但是…这段代码底层是如何工作的呢?我想我们中间不是所有人都能回答这个问题,我也不能。我认为我可以用高级编程语言写代码,例如 Haskell、Erlang、Go 等等,但是我完全不知道在编译之后它在底层是如何工作的。所以,我决定往下再深入一步,到汇编这个层次,并且记录下我的学习汇编之路。希望这是有趣的过程,而不是仅仅对我一个人。大约五、六年前我已经使用过汇编来写简单的程序,那时我还在上大学,用的是 Turbo 汇编和 DOS 操作系统。现在我使用 Linux-x86_64 操作系统,是的,64 位 Linux 和 16 位 DOS 肯定有很大的不同。那我们就开始吧。

Read more »
1…111213…17
ejunjsh

ejunjsh

code freak

164 posts
25 categories
154 tags
RSS
GitHub Weibo Email FB Page
0%
© 2014 — 2019 ejunjsh
Powered by Hexo
|
Theme — NexT.Gemini