注册 登录
编程论坛 Linux系统管理

计算机

madfrogme 发布于 2012-08-31 10:07, 9449 次点击
lstat() 与 stat() 类似, 但当文件是符号链接时,

lstat() 返回该符号链接的有关信息,

而不是由该符号链接引用文件的信息


[ 本帖最后由 madfrogme 于 2012-9-26 19:05 编辑 ]
71 回复
#2
madfrogme2012-08-31 10:08
We must be prepared for select() to return on error of EINTR

if we are catching signals
#3
madfrogme2012-08-31 10:25
umask为进程设置文件模式创建屏蔽字
常用的几种umask值
002: 阻止其他用户写你的文件
022: 阻止同组成员和其他用户写你的文件
027:  阻止同组成员写你的文件和其他用户读,写或执行你的文件
#4
madfrogme2012-08-31 13:31
使用 setbuf() 函数打开或是关闭缓冲机制

void setbuf( FILE *restrict fp, char *restrict buf);

int setvbuf( FILE *restrict fp, char *restrict buf, int mode, size_t size);


使用setvbuf() 来实现 setbuf()
setvbuf( stream, buf, buf? _IOFBUF: _IONBUF, BUFSIZ);


Portable applications should call setvbuf() only once on any given stream, and before any I/O is performed.

[ 本帖最后由 madfrogme 于 2012-8-31 14:33 编辑 ]
#5
madfrogme2012-08-31 13:44
当printf() 没有输出任何字符时, 如
printf("");
则返回0
#6
pangding2012-08-31 23:44
你在看什么书?
#7
madfrogme2012-08-31 23:50
回复 6楼 pangding
没有固定的书,在网上看到什么就是什么了,但最近主要就是linux的系统调用这一块
#8
madfrogme2012-08-31 23:52
nice() function calls the kernel set_user_nice() function which sets the static_prio and prio values in the stack's task_struct as appropriate

在用户空间可以通过nice 命令设置进程的静态优先级,这在内部会调用nice系统调用, 进程的nice 值在-20 到 19 之间(包含)值越低, 表明优先级越高

内核使用一个简单的数值范围, 从0到139(包含),用来表示内部优先级。 两样是值越低,优先级越高。 从0到99的范围专供实时进程使用

nice值【-20 , +19 】映射到范围100到139

光考虑静态优先级是不够的,应该考虑动态(prio)普通(normal_prio)和 静态(static_prio)优先级

static_prio 是计算的起点。 假定它已经设置好, 而内核现在想要计算其他优先级。则一行代码

p->prio = effective_prio(p);



[ 本帖最后由 madfrogme 于 2012-10-4 23:00 编辑 ]
#9
madfrogme2012-08-31 23:56
It's dsirable simply to iterate over all processes in the system. The task list is a doubly linked list
list_entry(task->next, struct task_struct, tasks)


list_entry() defined in linux/list.h
#10
madfrogme2012-09-01 09:23
/etc/passwd文件中可能会出现如下一行,类似于

squid:x:23:23: :/var/spool/squid:/dev/null

squid 的登录项的该字段为 /dev/null
显然这是一个设备,不能执行,因此将其用于此的目的是,
阻止任何人以用户squid 的名义登录到该系统
#11
madfrogme2012-09-01 09:48
struct passwd 结构体成员
程序代码:
#include <stdio.h>
#include <sys/types.h>
#include <pwd.h>

int main(void) {

    struct passwd *pw;

    pw = getpwuid(501);                    /*或者是 getpwnam("wzj"); 用来返回一个指向passwd结构体的指针*/

    printf("%s\n",pw->pw_name);     /*用户名*/

    printf("%s\n",pw->pw_passwd);   /*密码,用'*'表示*/

    printf("%d\n",pw->pw_uid);

    printf("%d\n",pw->pw_gid);

    printf("%s\n",pw->pw_gecos);    /*注释字段*/

    printf("%s\n",pw->pw_dir);      /*初始shell*/

    printf("%s\n",pw->pw_shell);

    return 0;
}


[ 本帖最后由 madfrogme 于 2012-9-1 10:51 编辑 ]
#12
madfrogme2012-09-01 10:05
gcc -std=c99 hello.c

启用gcc 的 1999 ISO C 扩展
#13
madfrogme2012-09-01 16:36
recv(), send() 函数  和 read(), write() 函数很相似,

区别在于最后一个最后一个int flags

flags 有一个可选项是 MSG_WAITALL

它告诉内核只有达到了要求数量的字节之后才返回,所以说如果系统支持这个选项, readn() 就可以参照如下定义

#define    readn(fd, ptr, n)     recv(fd, ptr, n, MSG_WAITALL)


但是就算指定了MSG_WAITALL, 若果有信号产生,或是连接中断,或是socket发生错误,

也不能按要求返回
#14
madfrogme2012-09-02 11:53
SYN segment contains only TCP header and IP header.

SYN flooding 也就是在受到服务器的SYN-ACK之后发送RST
#15
madfrogme2012-09-05 15:51
A pending error cause a socket to be both readable and writable

connect() 返回0 则表示成功了


[ 本帖最后由 madfrogme 于 2012-9-5 17:11 编辑 ]
#16
madfrogme2012-09-05 16:57
EINPROGRESS :
The socket is non-blocking and the connection cannot be completed immediately.

It is possible to  select() or poll() for completion by selecting socket for writing.

After select() indicates writablity,  use getsockopt() to read the SO_ERROR option at

level SOL_SOCKET to determine whether connect() completed successfully( SO_ERROR is zero)

or unsuccessfully (SO_ERROR is one of the usual error codes explaining the reason for the failure).
#17
madfrogme2012-09-06 09:32
What happens if our call to connect on a normal blocking socket is interrupted, say, by a caught signal? Assuming the connect is not automatically restarted, it returns EINTR, But, we cannot call connect again to wait for the connection to complete. Doing so will return EADDRINUSE
#18
madfrogme2012-09-12 22:30
The Memory Management Unit (MMU) transforms a logical address into a linear address by means of a hardware circuit called a segmentation unit ;
subsequently, a second hardware circuit called a paging unit transforms the linear address into a physical address


[ 本帖最后由 madfrogme 于 2012-9-13 00:03 编辑 ]
#19
madfrogme2012-09-12 22:53
一个设备驱动器可以通过两种方法使用DMA,
synchronous DMA and asynchronous DMA.(同步与非同步)
同步DMA的情况下,数据的传输是通过进程的激发,
非同步DMA的情况下,数据的传输是通过硬件设备的激发
同步DMA的一个例子就是一个正在播放音频的声卡。
一个用户态程序将声音数据写入一个设备文件,
这个设备文件和声卡的digital signal processor(DSP)相关联。
声卡驱动器将这些声音数据积累在内核缓冲区里,
同时,声卡驱动器又指示声卡在一个很好的时机
将声音数据从内核缓冲区复制到DSP,它会激发一个中断,
并且设备驱动器检查内核缓冲区是否还有
声音数据,如果有,驱动器再一次激发DMA数据传输
#20
madfrogme2012-09-12 23:03
A logical address consists of two parts:
a segment identifier and an offset that specifies
the relative address within the segment.

The segment identifier is a 16-bit field called the Segment Selector  
while the offset is a 32-bit field.
#21
madfrogme2012-09-12 23:41
Page cache一小例
when you first open a source file in a text editor,

data from the file is read into memory from disk.

As you edit the file, more and more pages are read in.

When you later compile the file,

the kernel can use the pages directly from the page cache;

it need not reread the file from disk.

Because users tend to read and manipulate the same files repeatedly,

the page cache reduces the need for a large number of disk operations.
#22
madfrogme2012-09-13 00:03
The Linux page cache aims to cache any page-based object, which includes many forms of files and memory mappings.

To remain generic, the Linux page cache uses the address_space structure to identify pages in the page cache. This structure is defined in <linux/fs.h>
#23
madfrogme2012-09-13 00:22
由于页高速缓存的缓存作用,写操作实际上会被延迟。当页高速缓存中的数据比后台存储的数据更新时,该数据就被称做脏数据。在内存中累积起来的脏页最终必须被写回磁盘。在以下两种情况发生时,脏页被写回磁盘:

·当空闲内存低于一个特定的阈值时,内核必须将脏页写回磁盘,以便释放内存。

·当脏页在内存中驻留时间超过一个特定的阈值时,内核必须将超时的脏页写回磁盘,以确保脏页不会无限期地驻留在内存中。

    上面两种工作的目的完全不同。实际上,在老内核中,这是由两个独立的内核线程分别完成的。但是在2.6内核中,由一群内核线程(pdflush后台回写例程)统一执行两种工作
#24
madfrogme2012-09-20 21:38
RCU(Read-Copy Update),顾名思义就是读-拷贝修改,它是基于其原理命名的。
对于被RCU保护的共享数据结构,读者不需要获得任何锁就可以访问它,
但写者在访问它时首先拷贝一个副本,然后对副本进行修改,
最后使用一个回调(callback)机制在适当的时机把指向原来数据的指针重新指向新的被修改的数据。
这个时机就是所有引用该数据的CPU都退出对共享数据的操作。
#25
madfrogme2012-09-20 21:57
> In function do_fork (), i see that we allocate some pidmap.
> Could someone please tell me -
> what is pidmap ?
> what is its use?
>

While creating a new process, we need to allocate and initialize a "struct pid" for it. In alloc_pid(),

the kernel tries to allocate & initialize the fields of struct pid.

One of the fields ("nr") is the actual NUMERIC pid (visible to user and for all other purposes) and it is initialized using alloc_pidmap().

The pidmap is just an efficient way to keep track of which all process IDs (numbers) are in use and which ones are not.

Basically we keep a bitmap of all the possible PIDs (1 bit for each PID).

The bit is set/unset depending upon whether the PID is allocated to some process or not.

alloc_pid() determines the number by simply checking the first bit that is set in the map.
#26
madfrogme2012-09-20 22:06
虚拟内存
只是作为一个例子,让我们假定您的程序正在访问地址为 629 的内存。
不过,虚拟内存系统不需要将其存储在位置为 629 的 RAM 中。
实际上,它甚至可以不在 RAM 中 —— 如果物理 RAM 已经满了,它甚至 可能已经被转移到硬盘上!
由于这类地址不必反映内存所在的物理位置,所以它们被称为虚拟内存。
操作系统维持着一个虚拟地址到物理地址的转换的表,以便计算机硬件可以正确地响应地址请求。
并且,如果地址在硬盘上而不是在 RAM 中,那么操作系统将暂时停止您的进程,将其他内存转存到硬盘中,从硬盘上加载被请求的内存, 然后再重新启动您的进程。
这样,每个进程都获得了自己可以使用的地址空间,可以访问比您物理上安装的内存更多的内存
#27
madfrogme2012-09-21 08:27
PID 的管理围绕两个数据结构展开, struct pid 是内核对PID的内部表示, 而struct upid 则表示特定的命名空间中可见的信息

struct upid {
        int nr;                    /*nr 表示ID的数值*/
        struct pid_namespace *ns;        /*ns是指向该ID所属的命名空间的指针*/
        struct hlist_node pid_chain;    /* pid_chain 用内核的标准方法实现了散列溢出链表*/
}
#28
madfrogme2012-09-21 10:31
Linux的fork 只复制页表,这样就建立了虚拟地址空间和物理内存页这间的联系

In linux, a thread is merry a process that shares certain resources with other processes.

Each thread has a unique task_struct and appears to the kernel as a normal process-- threads just happen to share resources, such as an address space,

with other processes.


[ 本帖最后由 madfrogme 于 2012-9-22 09:21 编辑 ]
#29
madfrogme2012-09-22 08:14
In the mm_release() function,

which is used when a task exits a memory address space,

vfork_done is checked to see whether it is NULL,

If it is not, the parent is signaled.

/* notify parent sleeping on vfork(), fork.c 的 mm_release()中 */

    if (vfork_done) {

        tsk->vfork_done = NULL;

        complete(vfork_done);
    }
#30
madfrogme2012-09-22 09:11
To work with threads you would need the header file linux/kthread.h
A thread is created by the call to the function
struct task_struct *kthread_create(int (*function)(void *data),
                                   void *data,
                                   const char name[],
                                   ...)
The function takes the following arguments 
function: The function that the thread has to execute
data : The "data" to be passed to the function 
name: The name by which the process will be recognised in the kernel. 

A thread created using the above call does not run but only gets created. To run the thread we need to call the function "wake_up_process" passing the thread id that is returned by "kthread_create". 

When the wake_up_process is called the function passed to kthread_create gets executed. 

To stop a thread that is running we need to call the kthread_stop(struct task_struct *threadid) where threadid is the same that is returned by the kthread_create call.
#31
madfrogme2012-09-22 18:16
it is possible to obtain the process descriptor of its parent with the following code:

struct task_struct *my_parent = current->parent;

Similarly, it is possible to iterate over a process's children with

struct task_struct *task;
struct list_head *list;
list_for_each(list, &current->children) {
    task = list_entry(list, struct task_struct, sibling);
    /* task now points to one of current's children */
}


user/include/linux/list.h 中
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr) – (unsigned long)(&((type *)0)->member)))


[ 本帖最后由 madfrogme 于 2012-9-22 19:28 编辑 ]
#32
madfrogme2012-09-23 00:36
enum pid_type
{
    PIDTYPE_PID,   进程的PID
    PIDTYPE_PGID,  进程组ID
    PIDTYPE_SID,   会话ID
    PIDTYPE_MAX
};

搞这么多个组是因为有需要给一个组同时发信号,
比如有时,使用 kill -9 杀一个程序,有了组的概念,就比较方便杀死相关的线程和进程。
会话也一样,你退出了telnet,就必须杀死你登录时创建的所有非后台进程。有了会话id,杀就非常方便。
#33
madfrogme2012-09-23 00:43
pid 结构体中嵌套着upid结构体, upid结构体中又嵌套着pid_namespace 结构体
#34
madfrogme2012-09-23 01:06
如何将task_struct 实例变为数字ID,

这个过程包含下面两个步骤

1. 获得与task_struct 关联的pid 实例,辅助函数task_pid, task_tgid, task_pgrp 和 task_session 分别用于取得 不同类型的ID.
<sched.h>
static inline struct pid *task_pid(struct task_struct *task)
{
        return task->pids[PIDTYPE_PID].pid;
}

kernel/pid.c
在获得pid 实例之后, 从struct pid 的 numbers 数组中的 uid 信息, 即可获得数字ID
pid_t pid_nr_ns ( struct pid *pid, struct pid_namespace *ns)
{
        struct upid *upid;
        pid_t nr = 0;
        if( pid && ns->level <= pid->level) {
                upid = &pid->numbers[ns->level];
                if(upid->ns == ns )
                        nr = upid->nr;
        }
        return nr;
}

因为父命名空间可以看到子命名空间的PID, 反过来却不行,

内核必须确保当前命名空间的level 小于或等于产生局部PID的命名空间的level

同样重要的是, 内核只需要关注产生全局PID
#35
madfrogme2012-09-24 09:49
可以使用如下方法查看页的大小, 单位是字节,一般linux的结果是4096
$ getconf PAGESIZE

或者
$ getconf PAGE_SIZE


[ 本帖最后由 madfrogme 于 2012-9-24 10:50 编辑 ]
#36
madfrogme2012-09-24 09:59
alloc_pidmap()函数,这个函数的功能就是分配新的空闲PID号,
其中有一句
offset = pid & BITS_PER_PAGE_MASK;

BITS_PER_PAGE_MASK的定义为如下

kernel/pid.c
53 #define BITS_PER_PAGE           (PAGE_SIZE*8)
54 #define BITS_PER_PAGE_MASK      (BITS_PER_PAGE-1)

PAGE_SIZE查到是4096, 所以BITS_PER_PAGE 就是32768, 2^15 (1,000,000,000,000,000)

所以BITS_PER_PAGE_MASK 就是( 0,111,111,111,111,111)了

于是pid & BITS_PER_PAGE_MASK; 就是取 pid的下15位了
所以offset 最大只能为32767


[ 本帖最后由 madfrogme 于 2012-9-24 11:02 编辑 ]
#37
madfrogme2012-09-24 10:24
几个和pid 有关的定义
include/linux/pid_namespace.h 中
 struct pidmap {
        atomic_t nr_free;
        void *page;
 };

#define PIDMAP_ENTRIES         ((PID_MAX_LIMIT + 8*PAGE_SIZE - 1)/PAGE_SIZE/8)

struct pid_namespace {
  ...
         struct pidmap pidmap[PIDMAP_ENTRIES];
         int last_pid;
         struct task_struct *child_reaper;
         struct kmem_cache *pid_cachep;
         unsigned int level;
         struct pid_namespace *parent;
 ...
}

include/linux/threads.h 文件

#ifndef _LINUX_THREADS_H
#define _LINUX_THREADS_H


/*
 * The default limit for the nr of threads is now in
 * /proc/sys/kernel/threads-max.
 */

/*
 * Maximum supported processors.  Setting this smaller saves quite a
 * bit of memory.  Use nr_cpu_ids instead of this except for static bitmaps.
 */
#ifndef CONFIG_NR_CPUS
/* FIXME: This should be fixed in the arch's Kconfig */
#define CONFIG_NR_CPUS    1
#endif

/* Places which use this should consider cpumask_var_t. */
#define NR_CPUS        CONFIG_NR_CPUS

#define MIN_THREADS_LEFT_FOR_ROOT 4

/*
 * This controls the default maximum pid allocated to a process
 */
#define PID_MAX_DEFAULT (CONFIG_BASE_SMALL ? 0x1000 : 0x8000)

/*
 * A maximum of 4 million PIDs should be enough for a while.
 * [NOTE: PID/TIDs are limited to 2^29 ~= 500+ million, see futex.h.]
 */
#define PID_MAX_LIMIT (CONFIG_BASE_SMALL ? PAGE_SIZE * 8 : \
    (sizeof(long) > 4 ? 4 * 1024 * 1024 : PID_MAX_DEFAULT))

#endif
#38
madfrogme2012-09-24 23:50
arch/x86/kernel/process.c 中
sys_fork 的定义

 int sys_fork(struct pt_regs *regs)
 {
         return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL);
 }

pt_regs 结构体在arch/x86/include/asm/ptrace.h中有定义

struct pt_regs {
    long ebx;
    long ecx;
    long edx;
    long esi;
    long edi;
    long ebp;
    long eax;
    int  xds;
    int  xes;
    int  xfs;
    int  xgs;
    long orig_eax;
    long eip;
    int  xcs;
    long eflags;
    long esp;
    int  xss;
};

実際にはシステムコール側の関数の引数宣言がどのような 形になっていてもスタックに積まれている値は struct pt_regs の形式になっており,

通常は最初の 5 個のうちのいくつかがシステムコール側で使用されるようになって います.

すべてのシステムコールは int 0x80 で entry.S の ENTRY(system_call) を 経由してカーネルの関数が呼び出されるため,

実はどのシステムコールでも同じ 情報を受け取っていることになります
#39
madfrogme2012-09-24 23:52
execve システムコールではレジスタに以下のような情報を渡す必要があります.

    ebx : (char *)filename,
    ecx : char ** argv,
    edx : char ** envp

なぜなら,sys_execve 中では do_execve に次のように情報を渡しています

do_execve(filename, (char **) regs.ecx, (char **) regs.edx, &regs);
#40
madfrogme2012-09-25 10:38
Page Table Entries (PTE)

A page table entry is what represents a page.

We will not cover the page table until a little later so dont worry too much about it.

However we will need to look at what an entry in the table looks like now. T

he x86 architecture defines a specific bit format for working with pages, so lets take a look at it.

Bit 0 (P): Present flag
0: Page is not in memory
1: Page is present (in memory)

Bit 1 (R/W): Read/Write flag
0: Page is read only
1: Page is writable

Bit 2 (U/S):User mode/Supervisor mode flag
0: Page is kernel (supervisor) mode
1: Page is user mode. Cannot read or write supervisor pages

Bits 3-4 (RSVD): Reserved by Intel

Bit 5 (A): Access flag. Set by processor
0: Page has not been accessed
1: Page has been accessed

Bit 6 (D): Dirty flag. Set by processor
0: Page has not been written to
1: Page has been written to

Bits 7-8 (RSVD): Reserved

Bits 9-11 (AVAIL): Available for use

Bits 12-31 (FRAME): Frame address


[ 本帖最后由 madfrogme 于 2012-9-25 11:45 编辑 ]
#41
madfrogme2012-09-25 10:57
Lets give out a simple example.

Lets say that we want this page to manage the 4KB address space beginning at physical location 1MB (0x100000).

What this means--to put in other words--is that this page is "mapped" to address 1MB.

To create this page, simply set 0x100000 in bits 12-31 (the frame address) of the page, and set the present bit. Voila--the page is mapped to 1MB. :) For example:

%define        PRIV        3
mov        ebx, 0x100000 | PRIV    ; this page is mapped to 1MB

Notice that 0x100000 is 4KB aligned? It ORs it with 3 (11 binary which sets the first two bits. Looking at the above table,

we can see that it sets the present and read/write flags, making this page present

 (Meaning its in physical memory. This is true as it is mapped from physical address 0x100000), and is writable.
#42
madfrogme2012-09-26 12:20
The syntax for the multiply command is

MUL    reg

reg may be any of the 24 general registers . If the register used is an eight-bit register, for example

MUL    BH

than the command means:

let AX = AL * BH

When an eight-bit register is used, it always multiplies by AL and stores the result in AX. When a 16-bit register is used, for example,

MUL BX

then the command mean:

let DX:AX = AX * BX

Where the 32-bit register is stored in two 16-bit registers. The top 16 bits are stored in DX, the bottom 16 bits in AX. When a 32-bit register is used, for example,

MUL EBX

then the command means:

let EDX:EAX = EAX * EBX

A single register is all that you specify when you use the MUL command.

The other registers are always implied.
#43
madfrogme2012-09-26 17:36
A computer uses 32-bit byte addressing.

The computer uses paged virtual memory with 4KB pages.

 Calculate the number of bits in the page number and offset fields of a logical address.

Answer

Since there are 4K bytes in a cache block,

the offset field must contain 12 bits (2^12 = 4K).

The remaining 20 bits are page number bits.

Thus a logical address is decomposed as shown below.

Page Number(20 bits) Offset(12 bits )


[ 本帖最后由 madfrogme 于 2012-9-26 18:38 编辑 ]
#44
madfrogme2012-09-26 19:48
プロセス空間領域の解放は、 exit_mmap() 関数(mm/mmap.c)で行われます。以下の処理を行います。

1.    ページテーブルに張り付いている実ページまたはスワップエントリの解放(unmap_vmas 関数)

2.    ページテーブルの解放(free_area_struct 関数)

3.    vm_ops のクローズオペレーションの実行、ファイル構造体の参照カウントデクリメント、および、vm_area_struct 構造体の解放(remove_vma 関数)
#45
madfrogme2012-09-27 16:19
mov bx, 1000h
mov ax, [bx]

这两句话的意思是把地址 1000h里的内容放入ax, 而不是把1000h放入ax,所以用了方括号


or    al, al        ; Does AL=0?

or可以用来判断AL是否为0,al中若有一位为0 则结果就不为0

LODSB     Load byte at address DS:(E)SI into AL


[ 本帖最后由 madfrogme 于 2012-9-28 20:34 编辑 ]
#46
madfrogme2012-09-27 21:50
bootloaders...

...Are stored with the Master Boot Record (MBR).
...Are in the first sector of the disk.
...Is the size of a single sector (512) bytes.
...Are loaded by the BIOS INT 0x19 at address 0x7C00.
#47
madfrogme2012-09-27 21:59
You can use the STI and CLI instructions to enable and disable all interrupts.

Most systems do not allow these instructions for applications as it can cause big problems (Although systems can emulate them).

cli        ; clear interrupts
 ; do something...
sti        ; enable interrupts--we're in the clear!


The ORG instruction is used to alter the value of the location counter.

ORG   addr

With an address specified, ORG changes the location counter to the location counter of addr.


[ 本帖最后由 madfrogme 于 2012-9-27 23:09 编辑 ]
#48
madfrogme2012-09-28 18:33
只有本站会员才能查看附件,请 登录
#49
madfrogme2012-09-28 19:12
There is some important things to remember about PMode(Protected Mode) however:

Absolutley no interrupts will be avilable. You will need to write them yourself. The use of any interrupt--hardware or software will cause a Triple Fault

Once you switch into pmode, the *slightest* mistake will cause a Triple Fault. Be carefull.

PMode requires the use of Descriptor Tables, such as the GDT, LDT, and IDTs.

PMode gives you access to 4 GB of Memory, With Memory Protection

Segment:Offset Addressing is used along with Linear Addressing

Access and use of 32 bit registers
#50
madfrogme2012-09-28 23:05
linux 0.11内核中, 为了有效地使用系统的物理内存,内存被划分成几个功能区域
只有本站会员才能查看附件,请 登录
#51
madfrogme2012-10-02 01:50

In AT&T syntax the size of memory operands is determined from the last character of the op-code name.

Op-code suffixes of ’b’, ’w’, and ’l’ specify byte(8-bit), word(16-bit), and long(32-bit) memory references.

Intel syntax accomplishes this by prefixing memory operands (not the op-codes) with ’byte ptr’, ’word ptr’, and ’dword ptr’.

Thus, Intel "mov al, byte ptr foo" is "movb foo, %al" in AT&T syntax.
12